@memberjunction/server 2.109.0 → 2.110.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.
Files changed (35) hide show
  1. package/dist/agents/skip-agent.d.ts +1 -0
  2. package/dist/agents/skip-agent.d.ts.map +1 -1
  3. package/dist/agents/skip-agent.js +65 -7
  4. package/dist/agents/skip-agent.js.map +1 -1
  5. package/dist/agents/skip-sdk.d.ts.map +1 -1
  6. package/dist/agents/skip-sdk.js +29 -14
  7. package/dist/agents/skip-sdk.js.map +1 -1
  8. package/dist/generated/generated.d.ts +34 -13
  9. package/dist/generated/generated.d.ts.map +1 -1
  10. package/dist/generated/generated.js +194 -86
  11. package/dist/generated/generated.js.map +1 -1
  12. package/dist/resolvers/CreateQueryResolver.d.ts +1 -0
  13. package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
  14. package/dist/resolvers/CreateQueryResolver.js +73 -11
  15. package/dist/resolvers/CreateQueryResolver.js.map +1 -1
  16. package/dist/resolvers/RunAIAgentResolver.d.ts +6 -2
  17. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  18. package/dist/resolvers/RunAIAgentResolver.js +234 -8
  19. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  20. package/dist/resolvers/TaskResolver.d.ts +1 -1
  21. package/dist/resolvers/TaskResolver.d.ts.map +1 -1
  22. package/dist/resolvers/TaskResolver.js +4 -3
  23. package/dist/resolvers/TaskResolver.js.map +1 -1
  24. package/dist/services/TaskOrchestrator.d.ts +3 -1
  25. package/dist/services/TaskOrchestrator.d.ts.map +1 -1
  26. package/dist/services/TaskOrchestrator.js +77 -2
  27. package/dist/services/TaskOrchestrator.js.map +1 -1
  28. package/package.json +35 -35
  29. package/src/agents/skip-agent.ts +93 -9
  30. package/src/agents/skip-sdk.ts +45 -16
  31. package/src/generated/generated.ts +135 -69
  32. package/src/resolvers/CreateQueryResolver.ts +125 -28
  33. package/src/resolvers/RunAIAgentResolver.ts +397 -9
  34. package/src/resolvers/TaskResolver.ts +3 -2
  35. package/src/services/TaskOrchestrator.ts +118 -3
@@ -31,7 +31,7 @@ import { GetAIAPIKey } from '@memberjunction/ai';
31
31
  import { CopyScalarsAndArrays } from '@memberjunction/global';
32
32
  import mssql from 'mssql';
33
33
  import { registerAccessToken, GetDataAccessToken } from '../resolvers/GetDataResolver.js';
34
- import { ConversationArtifactEntity, ConversationArtifactVersionEntity, ArtifactTypeEntity } from '@memberjunction/core-entities';
34
+ import { ArtifactTypeEntity } from '@memberjunction/core-entities';
35
35
  import { BehaviorSubject } from 'rxjs';
36
36
  import { take } from 'rxjs/operators';
37
37
 
@@ -452,16 +452,23 @@ export class SkipSDK {
452
452
 
453
453
  /**
454
454
  * Build artifacts for a conversation
455
+ * Uses ConversationDetailArtifact join table to get artifacts that were outputs from previous conversation details
456
+ * Direction = 'Output' means the artifact was generated by Skip, Direction = 'Input' means it was passed in
457
+ * Note: ConversationArtifact entity is deprecated - we now use the core Artifact entity
455
458
  */
456
459
  private async buildArtifacts(contextUser: UserInfo, dataSource: mssql.ConnectionPool, conversationId: string): Promise<SkipAPIArtifact[]> {
457
- const md = new Metadata();
458
- const ei = md.EntityByName('MJ: Conversation Artifacts');
459
460
  const rv = new RunView();
460
461
 
462
+ // Query ConversationDetailArtifact to find artifacts that were outputs (generated by Skip)
463
+ // These are the artifacts we want to pass back as context for future requests
461
464
  const results = await rv.RunViews([
462
465
  {
463
- EntityName: "MJ: Conversation Artifacts",
464
- ExtraFilter: `ConversationID='${conversationId}'`,
466
+ EntityName: "MJ: Conversation Detail Artifacts",
467
+ ExtraFilter: `Direction='Output' AND ConversationDetailID IN (SELECT ID FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwConversationDetails] WHERE ConversationID='${conversationId}')`,
468
+ OrderBy: "__mj_CreatedAt"
469
+ },
470
+ {
471
+ EntityName: "MJ: Artifacts",
465
472
  OrderBy: "__mj_CreatedAt"
466
473
  },
467
474
  {
@@ -469,9 +476,8 @@ export class SkipSDK {
469
476
  OrderBy: "Name"
470
477
  },
471
478
  {
472
- EntityName: "MJ: Conversation Artifact Versions",
473
- ExtraFilter: `ConversationArtifactID IN (SELECT ID FROM [${ei.SchemaName}].[${ei.BaseView}] WHERE ConversationID='${conversationId}')`,
474
- OrderBy: 'ConversationArtifactID, __mj_CreatedAt'
479
+ EntityName: "MJ: Artifact Versions",
480
+ OrderBy: 'ArtifactID, __mj_CreatedAt'
475
481
  }
476
482
  ], contextUser);
477
483
 
@@ -479,7 +485,15 @@ export class SkipSDK {
479
485
  return [];
480
486
  }
481
487
 
482
- const types = results[1].Results.map((a: ArtifactTypeEntity) => ({
488
+ // Get the artifact VERSION IDs from ConversationDetailArtifact where Direction='Output'
489
+ // ConversationDetailArtifact links to ArtifactVersionID, not ArtifactID directly
490
+ const outputVersionIds = new Set(
491
+ results[0].Results
492
+ .map((cda: any) => cda.ArtifactVersionID)
493
+ .filter(id => id) // Filter out null/undefined
494
+ );
495
+
496
+ const types = results[2].Results.map((a: ArtifactTypeEntity) => ({
483
497
  id: a.ID,
484
498
  name: a.Name,
485
499
  description: a.Description,
@@ -489,13 +503,28 @@ export class SkipSDK {
489
503
  updatedAt: a.__mj_UpdatedAt
490
504
  }));
491
505
 
492
- const artifacts = results[0].Results.map((a: ConversationArtifactEntity) => {
493
- const rawVersions: ConversationArtifactVersionEntity[] = results[2].Results as ConversationArtifactVersionEntity[];
494
- const thisArtifactsVersions = rawVersions.filter(rv => rv.ConversationArtifactID === a.ID);
506
+ // Get the versions that were outputs
507
+ const allVersions: any[] = results[3].Results as any[];
508
+ const outputVersions = allVersions.filter(v => outputVersionIds.has(v.ID));
509
+
510
+ // Group versions by their parent ArtifactID to build SkipAPIArtifact objects
511
+ const versionsByArtifactId = new Map<string, any[]>();
512
+ outputVersions.forEach(v => {
513
+ if (!versionsByArtifactId.has(v.ArtifactID)) {
514
+ versionsByArtifactId.set(v.ArtifactID, []);
515
+ }
516
+ versionsByArtifactId.get(v.ArtifactID)!.push(v);
517
+ });
518
+
519
+ const allArtifacts = results[1].Results as any[];
520
+ const artifacts = allArtifacts
521
+ .filter(a => versionsByArtifactId.has(a.ID)) // Only include artifacts that have output versions
522
+ .map((a: any) => {
523
+ const thisArtifactsVersions = versionsByArtifactId.get(a.ID) || [];
495
524
 
496
- const versions = thisArtifactsVersions.map((v: ConversationArtifactVersionEntity) => ({
525
+ const versions = thisArtifactsVersions.map((v: any) => ({
497
526
  id: v.ID,
498
- artifactId: v.ConversationArtifactID,
527
+ artifactId: v.ArtifactID,
499
528
  version: v.Version,
500
529
  configuration: v.Configuration,
501
530
  content: v.Content,
@@ -506,14 +535,14 @@ export class SkipSDK {
506
535
 
507
536
  return {
508
537
  id: a.ID,
509
- conversationId: a.ConversationID,
538
+ conversationId: conversationId, // Set from parameter since Artifact doesn't have ConversationID
510
539
  name: a.Name,
511
540
  description: a.Description,
512
541
  artifactType: types.find(t => t.id === a.ArtifactTypeID),
513
542
  sharingScope: a.SharingScope,
514
543
  currentVersion: versions.length > 0 ? Math.max(...versions.map(v => v.version)) : 1,
515
544
  versions,
516
- comments: '', // Default empty comments since it's required
545
+ comments: a.Comments || '', // Use artifact comments if available
517
546
  createdAt: a.__mj_CreatedAt,
518
547
  updatedAt: a.__mj_UpdatedAt
519
548
  };
@@ -1757,12 +1757,12 @@ each time the agent processes a prompt step.`})
1757
1757
  @MaxLength(16)
1758
1758
  RootLastRunID?: string;
1759
1759
 
1760
- @Field(() => [MJAIAgentRunStep_])
1761
- MJ_AIAgentRunSteps_AgentRunIDArray: MJAIAgentRunStep_[]; // Link to MJ_AIAgentRunSteps
1762
-
1763
1760
  @Field(() => [MJAIAgentRun_])
1764
1761
  MJ_AIAgentRuns_ParentRunIDArray: MJAIAgentRun_[]; // Link to MJ_AIAgentRuns
1765
1762
 
1763
+ @Field(() => [MJAIAgentRunStep_])
1764
+ MJ_AIAgentRunSteps_AgentRunIDArray: MJAIAgentRunStep_[]; // Link to MJ_AIAgentRunSteps
1765
+
1766
1766
  @Field(() => [MJAIPromptRun_])
1767
1767
  MJ_AIPromptRuns_AgentRunIDArray: MJAIPromptRun_[]; // Link to MJ_AIPromptRuns
1768
1768
 
@@ -2070,25 +2070,25 @@ export class MJAIAgentRunResolver extends ResolverBase {
2070
2070
  return result;
2071
2071
  }
2072
2072
 
2073
- @FieldResolver(() => [MJAIAgentRunStep_])
2074
- async MJ_AIAgentRunSteps_AgentRunIDArray(@Root() mjaiagentrun_: MJAIAgentRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2075
- this.CheckUserReadPermissions('MJ: AI Agent Run Steps', userPayload);
2073
+ @FieldResolver(() => [MJAIAgentRun_])
2074
+ async MJ_AIAgentRuns_ParentRunIDArray(@Root() mjaiagentrun_: MJAIAgentRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2075
+ this.CheckUserReadPermissions('MJ: AI Agent Runs', userPayload);
2076
2076
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2077
2077
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2078
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentRunSteps] WHERE [AgentRunID]='${mjaiagentrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Run Steps', userPayload, EntityPermissionType.Read, 'AND');
2078
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentRuns] WHERE [ParentRunID]='${mjaiagentrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Runs', userPayload, EntityPermissionType.Read, 'AND');
2079
2079
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2080
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Run Steps', rows);
2080
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Runs', rows);
2081
2081
  return result;
2082
2082
  }
2083
2083
 
2084
- @FieldResolver(() => [MJAIAgentRun_])
2085
- async MJ_AIAgentRuns_ParentRunIDArray(@Root() mjaiagentrun_: MJAIAgentRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2086
- this.CheckUserReadPermissions('MJ: AI Agent Runs', userPayload);
2084
+ @FieldResolver(() => [MJAIAgentRunStep_])
2085
+ async MJ_AIAgentRunSteps_AgentRunIDArray(@Root() mjaiagentrun_: MJAIAgentRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2086
+ this.CheckUserReadPermissions('MJ: AI Agent Run Steps', userPayload);
2087
2087
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2088
2088
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2089
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentRuns] WHERE [ParentRunID]='${mjaiagentrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Runs', userPayload, EntityPermissionType.Read, 'AND');
2089
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentRunSteps] WHERE [AgentRunID]='${mjaiagentrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Run Steps', userPayload, EntityPermissionType.Read, 'AND');
2090
2090
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2091
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Runs', rows);
2091
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Run Steps', rows);
2092
2092
  return result;
2093
2093
  }
2094
2094
 
@@ -2875,9 +2875,9 @@ export class MJAIAgent_ {
2875
2875
  @MaxLength(16)
2876
2876
  TypeID?: string;
2877
2877
 
2878
- @Field({nullable: true, description: `Current status of the AI agent. Active agents can be executed, Disabled agents are inactive, and Pending agents are awaiting configuration or approval. Allowed values: Active, Disabled, Pending.`})
2878
+ @Field({description: `Current status of the AI agent. Active agents can be executed, Disabled agents are inactive, and Pending agents are awaiting configuration or approval. Allowed values: Active, Disabled, Pending.`})
2879
2879
  @MaxLength(40)
2880
- Status?: string;
2880
+ Status: string;
2881
2881
 
2882
2882
  @Field({nullable: true, description: `Optional override for the class name used by the MemberJunction class factory to instantiate this specific agent. If specified, this overrides the agent type's DriverClass. Useful for specialized agent implementations.`})
2883
2883
  @MaxLength(510)
@@ -2967,6 +2967,16 @@ if this limit is exceeded.`})
2967
2967
  @MaxLength(40)
2968
2968
  InvocationMode: string;
2969
2969
 
2970
+ @Field({description: `Controls how artifacts are created from this agent's payloads. "Always" creates visible artifacts, "Never" skips artifact creation, "System Only" creates hidden system artifacts.`})
2971
+ @MaxLength(40)
2972
+ ArtifactCreationMode: string;
2973
+
2974
+ @Field({nullable: true, description: `Detailed markdown formatted requirements that explain the business goals of the agent without specific technical implementation details.`})
2975
+ FunctionalRequirements?: string;
2976
+
2977
+ @Field({nullable: true, description: `Detailed markdown that explains the structure of the agent including agent architecture, actions, sub-agents, prompts, and payload structure.`})
2978
+ TechnicalDesign?: string;
2979
+
2970
2980
  @Field({nullable: true})
2971
2981
  @MaxLength(510)
2972
2982
  Parent?: string;
@@ -3095,7 +3105,7 @@ export class CreateMJAIAgentInput {
3095
3105
  TypeID: string | null;
3096
3106
 
3097
3107
  @Field({ nullable: true })
3098
- Status: string | null;
3108
+ Status?: string;
3099
3109
 
3100
3110
  @Field({ nullable: true })
3101
3111
  DriverClass: string | null;
@@ -3168,6 +3178,15 @@ export class CreateMJAIAgentInput {
3168
3178
 
3169
3179
  @Field({ nullable: true })
3170
3180
  InvocationMode?: string;
3181
+
3182
+ @Field({ nullable: true })
3183
+ ArtifactCreationMode?: string;
3184
+
3185
+ @Field({ nullable: true })
3186
+ FunctionalRequirements: string | null;
3187
+
3188
+ @Field({ nullable: true })
3189
+ TechnicalDesign: string | null;
3171
3190
  }
3172
3191
 
3173
3192
 
@@ -3216,7 +3235,7 @@ export class UpdateMJAIAgentInput {
3216
3235
  TypeID?: string | null;
3217
3236
 
3218
3237
  @Field({ nullable: true })
3219
- Status?: string | null;
3238
+ Status?: string;
3220
3239
 
3221
3240
  @Field({ nullable: true })
3222
3241
  DriverClass?: string | null;
@@ -3290,6 +3309,15 @@ export class UpdateMJAIAgentInput {
3290
3309
  @Field({ nullable: true })
3291
3310
  InvocationMode?: string;
3292
3311
 
3312
+ @Field({ nullable: true })
3313
+ ArtifactCreationMode?: string;
3314
+
3315
+ @Field({ nullable: true })
3316
+ FunctionalRequirements?: string | null;
3317
+
3318
+ @Field({ nullable: true })
3319
+ TechnicalDesign?: string | null;
3320
+
3293
3321
  @Field(() => [KeyValuePairInput], { nullable: true })
3294
3322
  OldValues___?: KeyValuePairInput[];
3295
3323
  }
@@ -6755,12 +6783,12 @@ export class MJAIPrompt_ {
6755
6783
  @Field(() => [MJAIPrompt_])
6756
6784
  AIPrompts_ResultSelectorPromptIDArray: MJAIPrompt_[]; // Link to AIPrompts
6757
6785
 
6758
- @Field(() => [MJAIPromptModel_])
6759
- MJ_AIPromptModels_PromptIDArray: MJAIPromptModel_[]; // Link to MJ_AIPromptModels
6760
-
6761
6786
  @Field(() => [MJAIAgentPrompt_])
6762
6787
  MJ_AIAgentPrompts_PromptIDArray: MJAIAgentPrompt_[]; // Link to MJ_AIAgentPrompts
6763
6788
 
6789
+ @Field(() => [MJAIPromptModel_])
6790
+ MJ_AIPromptModels_PromptIDArray: MJAIPromptModel_[]; // Link to MJ_AIPromptModels
6791
+
6764
6792
  @Field(() => [MJAIAgentStep_])
6765
6793
  MJ_AIAgentSteps_PromptIDArray: MJAIAgentStep_[]; // Link to MJ_AIAgentSteps
6766
6794
 
@@ -7209,25 +7237,25 @@ export class MJAIPromptResolver extends ResolverBase {
7209
7237
  return result;
7210
7238
  }
7211
7239
 
7212
- @FieldResolver(() => [MJAIPromptModel_])
7213
- async MJ_AIPromptModels_PromptIDArray(@Root() mjaiprompt_: MJAIPrompt_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
7214
- this.CheckUserReadPermissions('MJ: AI Prompt Models', userPayload);
7240
+ @FieldResolver(() => [MJAIAgentPrompt_])
7241
+ async MJ_AIAgentPrompts_PromptIDArray(@Root() mjaiprompt_: MJAIPrompt_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
7242
+ this.CheckUserReadPermissions('MJ: AI Agent Prompts', userPayload);
7215
7243
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
7216
7244
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
7217
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIPromptModels] WHERE [PromptID]='${mjaiprompt_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Prompt Models', userPayload, EntityPermissionType.Read, 'AND');
7245
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentPrompts] WHERE [PromptID]='${mjaiprompt_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Prompts', userPayload, EntityPermissionType.Read, 'AND');
7218
7246
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
7219
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Prompt Models', rows);
7247
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Prompts', rows);
7220
7248
  return result;
7221
7249
  }
7222
7250
 
7223
- @FieldResolver(() => [MJAIAgentPrompt_])
7224
- async MJ_AIAgentPrompts_PromptIDArray(@Root() mjaiprompt_: MJAIPrompt_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
7225
- this.CheckUserReadPermissions('MJ: AI Agent Prompts', userPayload);
7251
+ @FieldResolver(() => [MJAIPromptModel_])
7252
+ async MJ_AIPromptModels_PromptIDArray(@Root() mjaiprompt_: MJAIPrompt_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
7253
+ this.CheckUserReadPermissions('MJ: AI Prompt Models', userPayload);
7226
7254
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
7227
7255
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
7228
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentPrompts] WHERE [PromptID]='${mjaiprompt_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Prompts', userPayload, EntityPermissionType.Read, 'AND');
7256
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIPromptModels] WHERE [PromptID]='${mjaiprompt_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Prompt Models', userPayload, EntityPermissionType.Read, 'AND');
7229
7257
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
7230
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Prompts', rows);
7258
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Prompt Models', rows);
7231
7259
  return result;
7232
7260
  }
7233
7261
 
@@ -11216,12 +11244,12 @@ export class MJEntity_ {
11216
11244
  @Field(() => [MJQueryEntity_])
11217
11245
  QueryEntities_EntityIDArray: MJQueryEntity_[]; // Link to QueryEntities
11218
11246
 
11219
- @Field(() => [MJRecordLink_])
11220
- MJ_RecordLinks_SourceEntityIDArray: MJRecordLink_[]; // Link to MJ_RecordLinks
11221
-
11222
11247
  @Field(() => [MJAccessControlRule_])
11223
11248
  MJ_AccessControlRules_EntityIDArray: MJAccessControlRule_[]; // Link to MJ_AccessControlRules
11224
11249
 
11250
+ @Field(() => [MJRecordLink_])
11251
+ MJ_RecordLinks_SourceEntityIDArray: MJRecordLink_[]; // Link to MJ_RecordLinks
11252
+
11225
11253
  @Field(() => [MJGeneratedCode_])
11226
11254
  GeneratedCodes_LinkedEntityIDArray: MJGeneratedCode_[]; // Link to GeneratedCodes
11227
11255
 
@@ -12029,25 +12057,25 @@ export class MJEntityResolverBase extends ResolverBase {
12029
12057
  return result;
12030
12058
  }
12031
12059
 
12032
- @FieldResolver(() => [MJRecordLink_])
12033
- async MJ_RecordLinks_SourceEntityIDArray(@Root() mjentity_: MJEntity_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12034
- this.CheckUserReadPermissions('MJ: Record Links', userPayload);
12060
+ @FieldResolver(() => [MJAccessControlRule_])
12061
+ async MJ_AccessControlRules_EntityIDArray(@Root() mjentity_: MJEntity_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12062
+ this.CheckUserReadPermissions('MJ: Access Control Rules', userPayload);
12035
12063
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
12036
12064
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
12037
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwRecordLinks] WHERE [SourceEntityID]='${mjentity_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Record Links', userPayload, EntityPermissionType.Read, 'AND');
12065
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAccessControlRules] WHERE [EntityID]='${mjentity_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Access Control Rules', userPayload, EntityPermissionType.Read, 'AND');
12038
12066
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
12039
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Record Links', rows);
12067
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Access Control Rules', rows);
12040
12068
  return result;
12041
12069
  }
12042
12070
 
12043
- @FieldResolver(() => [MJAccessControlRule_])
12044
- async MJ_AccessControlRules_EntityIDArray(@Root() mjentity_: MJEntity_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12045
- this.CheckUserReadPermissions('MJ: Access Control Rules', userPayload);
12071
+ @FieldResolver(() => [MJRecordLink_])
12072
+ async MJ_RecordLinks_SourceEntityIDArray(@Root() mjentity_: MJEntity_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12073
+ this.CheckUserReadPermissions('MJ: Record Links', userPayload);
12046
12074
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
12047
12075
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
12048
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAccessControlRules] WHERE [EntityID]='${mjentity_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Access Control Rules', userPayload, EntityPermissionType.Read, 'AND');
12076
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwRecordLinks] WHERE [SourceEntityID]='${mjentity_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Record Links', userPayload, EntityPermissionType.Read, 'AND');
12049
12077
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
12050
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Access Control Rules', rows);
12078
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Record Links', rows);
12051
12079
  return result;
12052
12080
  }
12053
12081
 
@@ -12162,6 +12190,13 @@ export class MJUser_ {
12162
12190
  @MaxLength(10)
12163
12191
  _mj__UpdatedAt: Date;
12164
12192
 
12193
+ @Field({nullable: true, description: `User avatar image. Can be a Base64 encoded data URI (e.g., "data:image/png;base64,...") or a URL to an image file. Preferred over UserImageIconClass when present. Recommended for small thumbnail images only to maintain performance.`})
12194
+ UserImageURL?: string;
12195
+
12196
+ @Field({nullable: true, description: `Font Awesome icon class for user avatar (e.g., "fa-solid fa-user-astronaut"). Used as fallback when UserImageURL is not provided. Example classes: "fa-solid fa-user", "fa-regular fa-circle-user", "fa-solid fa-user-tie".`})
12197
+ @MaxLength(200)
12198
+ UserImageIconClass?: string;
12199
+
12165
12200
  @Field({nullable: true})
12166
12201
  @MaxLength(202)
12167
12202
  FirstLast?: string;
@@ -12294,24 +12329,24 @@ export class MJUser_ {
12294
12329
  @Field(() => [MJReportUserState_])
12295
12330
  MJ_ReportUserStates_UserIDArray: MJReportUserState_[]; // Link to MJ_ReportUserStates
12296
12331
 
12297
- @Field(() => [MJDashboardUserPreference_])
12298
- MJ_DashboardUserPreferences_UserIDArray: MJDashboardUserPreference_[]; // Link to MJ_DashboardUserPreferences
12299
-
12300
12332
  @Field(() => [MJDashboardUserState_])
12301
12333
  MJ_DashboardUserStates_UserIDArray: MJDashboardUserState_[]; // Link to MJ_DashboardUserStates
12302
12334
 
12335
+ @Field(() => [MJDashboardUserPreference_])
12336
+ MJ_DashboardUserPreferences_UserIDArray: MJDashboardUserPreference_[]; // Link to MJ_DashboardUserPreferences
12337
+
12303
12338
  @Field(() => [MJArtifactVersion_])
12304
12339
  MJ_ArtifactVersions_UserIDArray: MJArtifactVersion_[]; // Link to MJ_ArtifactVersions
12305
12340
 
12306
12341
  @Field(() => [MJPublicLink_])
12307
12342
  MJ_PublicLinks_UserIDArray: MJPublicLink_[]; // Link to MJ_PublicLinks
12308
12343
 
12309
- @Field(() => [MJScheduledJobRun_])
12310
- MJ_ScheduledJobRuns_ExecutedByUserIDArray: MJScheduledJobRun_[]; // Link to MJ_ScheduledJobRuns
12311
-
12312
12344
  @Field(() => [MJScheduledJob_])
12313
12345
  MJ_ScheduledJobs_NotifyUserIDArray: MJScheduledJob_[]; // Link to MJ_ScheduledJobs
12314
12346
 
12347
+ @Field(() => [MJScheduledJobRun_])
12348
+ MJ_ScheduledJobRuns_ExecutedByUserIDArray: MJScheduledJobRun_[]; // Link to MJ_ScheduledJobRuns
12349
+
12315
12350
  @Field(() => [MJArtifactPermission_])
12316
12351
  MJ_ArtifactPermissions_UserIDArray: MJArtifactPermission_[]; // Link to MJ_ArtifactPermissions
12317
12352
 
@@ -12399,6 +12434,12 @@ export class CreateMJUserInput {
12399
12434
 
12400
12435
  @Field({ nullable: true })
12401
12436
  EmployeeID: string | null;
12437
+
12438
+ @Field({ nullable: true })
12439
+ UserImageURL: string | null;
12440
+
12441
+ @Field({ nullable: true })
12442
+ UserImageIconClass: string | null;
12402
12443
  }
12403
12444
 
12404
12445
 
@@ -12443,6 +12484,12 @@ export class UpdateMJUserInput {
12443
12484
  @Field({ nullable: true })
12444
12485
  EmployeeID?: string | null;
12445
12486
 
12487
+ @Field({ nullable: true })
12488
+ UserImageURL?: string | null;
12489
+
12490
+ @Field({ nullable: true })
12491
+ UserImageIconClass?: string | null;
12492
+
12446
12493
  @Field(() => [KeyValuePairInput], { nullable: true })
12447
12494
  OldValues___?: KeyValuePairInput[];
12448
12495
  }
@@ -12912,25 +12959,25 @@ export class MJUserResolverBase extends ResolverBase {
12912
12959
  return result;
12913
12960
  }
12914
12961
 
12915
- @FieldResolver(() => [MJDashboardUserPreference_])
12916
- async MJ_DashboardUserPreferences_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12917
- this.CheckUserReadPermissions('MJ: Dashboard User Preferences', userPayload);
12962
+ @FieldResolver(() => [MJDashboardUserState_])
12963
+ async MJ_DashboardUserStates_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12964
+ this.CheckUserReadPermissions('MJ: Dashboard User States', userPayload);
12918
12965
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
12919
12966
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
12920
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserPreferences] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User Preferences', userPayload, EntityPermissionType.Read, 'AND');
12967
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserStates] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User States', userPayload, EntityPermissionType.Read, 'AND');
12921
12968
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
12922
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User Preferences', rows);
12969
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User States', rows);
12923
12970
  return result;
12924
12971
  }
12925
12972
 
12926
- @FieldResolver(() => [MJDashboardUserState_])
12927
- async MJ_DashboardUserStates_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12928
- this.CheckUserReadPermissions('MJ: Dashboard User States', userPayload);
12973
+ @FieldResolver(() => [MJDashboardUserPreference_])
12974
+ async MJ_DashboardUserPreferences_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12975
+ this.CheckUserReadPermissions('MJ: Dashboard User Preferences', userPayload);
12929
12976
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
12930
12977
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
12931
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserStates] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User States', userPayload, EntityPermissionType.Read, 'AND');
12978
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserPreferences] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User Preferences', userPayload, EntityPermissionType.Read, 'AND');
12932
12979
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
12933
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User States', rows);
12980
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User Preferences', rows);
12934
12981
  return result;
12935
12982
  }
12936
12983
 
@@ -12956,25 +13003,25 @@ export class MJUserResolverBase extends ResolverBase {
12956
13003
  return result;
12957
13004
  }
12958
13005
 
12959
- @FieldResolver(() => [MJScheduledJobRun_])
12960
- async MJ_ScheduledJobRuns_ExecutedByUserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12961
- this.CheckUserReadPermissions('MJ: Scheduled Job Runs', userPayload);
13006
+ @FieldResolver(() => [MJScheduledJob_])
13007
+ async MJ_ScheduledJobs_NotifyUserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
13008
+ this.CheckUserReadPermissions('MJ: Scheduled Jobs', userPayload);
12962
13009
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
12963
13010
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
12964
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwScheduledJobRuns] WHERE [ExecutedByUserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Scheduled Job Runs', userPayload, EntityPermissionType.Read, 'AND');
13011
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwScheduledJobs] WHERE [NotifyUserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Scheduled Jobs', userPayload, EntityPermissionType.Read, 'AND');
12965
13012
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
12966
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Scheduled Job Runs', rows);
13013
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Scheduled Jobs', rows);
12967
13014
  return result;
12968
13015
  }
12969
13016
 
12970
- @FieldResolver(() => [MJScheduledJob_])
12971
- async MJ_ScheduledJobs_NotifyUserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
12972
- this.CheckUserReadPermissions('MJ: Scheduled Jobs', userPayload);
13017
+ @FieldResolver(() => [MJScheduledJobRun_])
13018
+ async MJ_ScheduledJobRuns_ExecutedByUserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
13019
+ this.CheckUserReadPermissions('MJ: Scheduled Job Runs', userPayload);
12973
13020
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
12974
13021
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
12975
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwScheduledJobs] WHERE [NotifyUserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Scheduled Jobs', userPayload, EntityPermissionType.Read, 'AND');
13022
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwScheduledJobRuns] WHERE [ExecutedByUserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Scheduled Job Runs', userPayload, EntityPermissionType.Read, 'AND');
12976
13023
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
12977
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Scheduled Jobs', rows);
13024
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Scheduled Job Runs', rows);
12978
13025
  return result;
12979
13026
  }
12980
13027
 
@@ -34393,6 +34440,9 @@ export class MJCommunicationProvider_ {
34393
34440
  @Field(() => Boolean, {description: `Whether or not the provider supports replying to messages`})
34394
34441
  SupportsReplying: boolean;
34395
34442
 
34443
+ @Field(() => Boolean, {description: `Whether or not the provider supports creating draft messages`})
34444
+ SupportsDrafts: boolean;
34445
+
34396
34446
  @Field(() => [MJCommunicationProviderMessageType_])
34397
34447
  CommunicationProviderMessageTypes_CommunicationProviderIDArray: MJCommunicationProviderMessageType_[]; // Link to CommunicationProviderMessageTypes
34398
34448
 
@@ -34432,6 +34482,9 @@ export class CreateMJCommunicationProviderInput {
34432
34482
 
34433
34483
  @Field(() => Boolean, { nullable: true })
34434
34484
  SupportsReplying?: boolean;
34485
+
34486
+ @Field(() => Boolean, { nullable: true })
34487
+ SupportsDrafts?: boolean;
34435
34488
  }
34436
34489
 
34437
34490
 
@@ -34467,6 +34520,9 @@ export class UpdateMJCommunicationProviderInput {
34467
34520
  @Field(() => Boolean, { nullable: true })
34468
34521
  SupportsReplying?: boolean;
34469
34522
 
34523
+ @Field(() => Boolean, { nullable: true })
34524
+ SupportsDrafts?: boolean;
34525
+
34470
34526
  @Field(() => [KeyValuePairInput], { nullable: true })
34471
34527
  OldValues___?: KeyValuePairInput[];
34472
34528
  }
@@ -41803,6 +41859,10 @@ export class MJArtifact_ {
41803
41859
  @MaxLength(10)
41804
41860
  _mj__UpdatedAt: Date;
41805
41861
 
41862
+ @Field({description: `Controls artifact visibility in user-facing lists. "Always" shows in all lists, "System Only" hides from normal views (for system-generated artifacts like agent routing payloads).`})
41863
+ @MaxLength(40)
41864
+ Visibility: string;
41865
+
41806
41866
  @Field()
41807
41867
  @MaxLength(510)
41808
41868
  Environment: string;
@@ -41851,6 +41911,9 @@ export class CreateMJArtifactInput {
41851
41911
 
41852
41912
  @Field({ nullable: true })
41853
41913
  UserID?: string;
41914
+
41915
+ @Field({ nullable: true })
41916
+ Visibility?: string;
41854
41917
  }
41855
41918
 
41856
41919
 
@@ -41880,6 +41943,9 @@ export class UpdateMJArtifactInput {
41880
41943
  @Field({ nullable: true })
41881
41944
  UserID?: string;
41882
41945
 
41946
+ @Field({ nullable: true })
41947
+ Visibility?: string;
41948
+
41883
41949
  @Field(() => [KeyValuePairInput], { nullable: true })
41884
41950
  OldValues___?: KeyValuePairInput[];
41885
41951
  }