@memberjunction/server 2.104.0 → 2.106.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 (78) hide show
  1. package/dist/agents/skip-agent.d.ts +1 -1
  2. package/dist/agents/skip-agent.d.ts.map +1 -1
  3. package/dist/agents/skip-agent.js +1189 -24
  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 +3 -4
  7. package/dist/agents/skip-sdk.js.map +1 -1
  8. package/dist/generated/generated.d.ts +3621 -3407
  9. package/dist/generated/generated.d.ts.map +1 -1
  10. package/dist/generated/generated.js +21331 -19952
  11. package/dist/generated/generated.js.map +1 -1
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +5 -18
  15. package/dist/index.js.map +1 -1
  16. package/dist/resolvers/CreateQueryResolver.d.ts +2 -2
  17. package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
  18. package/dist/resolvers/CreateQueryResolver.js +12 -12
  19. package/dist/resolvers/CreateQueryResolver.js.map +1 -1
  20. package/dist/resolvers/EntityResolver.d.ts +2 -2
  21. package/dist/resolvers/EntityResolver.d.ts.map +1 -1
  22. package/dist/resolvers/EntityResolver.js +4 -4
  23. package/dist/resolvers/EntityResolver.js.map +1 -1
  24. package/dist/resolvers/FileCategoryResolver.d.ts +1 -1
  25. package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
  26. package/dist/resolvers/FileCategoryResolver.js +2 -2
  27. package/dist/resolvers/FileCategoryResolver.js.map +1 -1
  28. package/dist/resolvers/FileResolver.d.ts +6 -6
  29. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  30. package/dist/resolvers/FileResolver.js +14 -14
  31. package/dist/resolvers/FileResolver.js.map +1 -1
  32. package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
  33. package/dist/resolvers/PotentialDuplicateRecordResolver.js +0 -2
  34. package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
  35. package/dist/resolvers/RunAIAgentResolver.d.ts +2 -2
  36. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  37. package/dist/resolvers/RunAIAgentResolver.js +21 -17
  38. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  39. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  40. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  41. package/dist/resolvers/TaskResolver.d.ts +18 -0
  42. package/dist/resolvers/TaskResolver.d.ts.map +1 -0
  43. package/dist/resolvers/TaskResolver.js +138 -0
  44. package/dist/resolvers/TaskResolver.js.map +1 -0
  45. package/dist/resolvers/UserFavoriteResolver.d.ts +2 -2
  46. package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
  47. package/dist/resolvers/UserFavoriteResolver.js +5 -5
  48. package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
  49. package/dist/resolvers/UserResolver.d.ts +2 -2
  50. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  51. package/dist/resolvers/UserResolver.js +7 -7
  52. package/dist/resolvers/UserResolver.js.map +1 -1
  53. package/dist/resolvers/UserViewResolver.d.ts +2 -2
  54. package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
  55. package/dist/resolvers/UserViewResolver.js +8 -8
  56. package/dist/resolvers/UserViewResolver.js.map +1 -1
  57. package/dist/services/TaskOrchestrator.d.ts +52 -0
  58. package/dist/services/TaskOrchestrator.d.ts.map +1 -0
  59. package/dist/services/TaskOrchestrator.js +486 -0
  60. package/dist/services/TaskOrchestrator.js.map +1 -0
  61. package/package.json +30 -38
  62. package/src/agents/skip-agent.ts +1176 -28
  63. package/src/agents/skip-sdk.ts +3 -5
  64. package/src/generated/generated.ts +7664 -6785
  65. package/src/index.ts +7 -21
  66. package/src/resolvers/CreateQueryResolver.ts +6 -6
  67. package/src/resolvers/EntityResolver.ts +4 -4
  68. package/src/resolvers/FileCategoryResolver.ts +2 -2
  69. package/src/resolvers/FileResolver.ts +12 -12
  70. package/src/resolvers/PotentialDuplicateRecordResolver.ts +2 -3
  71. package/src/resolvers/RunAIAgentResolver.ts +7 -0
  72. package/src/resolvers/RunTemplateResolver.ts +1 -2
  73. package/src/resolvers/TaskResolver.ts +142 -0
  74. package/src/resolvers/UserFavoriteResolver.ts +5 -5
  75. package/src/resolvers/UserResolver.ts +7 -7
  76. package/src/resolvers/UserViewResolver.ts +8 -8
  77. package/src/services/TaskOrchestration-Integration.md +188 -0
  78. package/src/services/TaskOrchestrator.ts +756 -0
package/src/index.ts CHANGED
@@ -44,28 +44,10 @@ LoadAgentManagementActions();
44
44
  import { resolve } from 'node:path';
45
45
  import { DataSourceInfo, raiseEvent } from './types.js';
46
46
  import { LoadAIEngine } from '@memberjunction/aiengine';
47
- import { LoadOpenAILLM } from '@memberjunction/ai-openai';
48
- import { LoadAnthropicLLM } from '@memberjunction/ai-anthropic';
49
- import { LoadGroqLLM } from '@memberjunction/ai-groq';
50
- import { LoadCerebrasLLM } from '@memberjunction/ai-cerebras';
51
- import { LoadMistralLLM } from '@memberjunction/ai-mistral';
52
- import { LoadLMStudioLLM } from '@memberjunction/ai-lmstudio';
53
- import { LoadOpenRouterLLM } from '@memberjunction/ai-openrouter';
54
- import { LoadOllamaLLM } from '@memberjunction/ai-ollama';
55
- import { LoadLocalEmbedding } from '@memberjunction/ai-local-embeddings';
56
- // Load AI LLMs and Base AI Engine
57
- // These imports are necessary to ensure the LLMs are registered in the MemberJunction AI
58
- // system. They are not tree-shaken because they are dynamically loaded at runtime.
47
+ import { LoadAIProviders } from '@memberjunction/ai-provider-bundle';
48
+ // Load AI Engine and all providers to prevent tree shaking
59
49
  LoadAIEngine();
60
- LoadOpenAILLM();
61
- LoadAnthropicLLM();
62
- LoadGroqLLM();
63
- LoadCerebrasLLM();
64
- LoadMistralLLM();
65
- LoadLMStudioLLM();
66
- LoadOpenRouterLLM();
67
- LoadOllamaLLM();
68
- LoadLocalEmbedding();
50
+ LoadAIProviders();
69
51
 
70
52
  import { ExternalChangeDetectorEngine } from '@memberjunction/external-change-detection';
71
53
 
@@ -86,10 +68,14 @@ export * from './generic/RunViewResolver.js';
86
68
  export * from './resolvers/RunTemplateResolver.js';
87
69
  export * from './resolvers/RunAIPromptResolver.js';
88
70
  export * from './resolvers/RunAIAgentResolver.js';
71
+ export * from './resolvers/TaskResolver.js';
89
72
  export * from './generic/KeyValuePairInput.js';
90
73
  export * from './generic/KeyInputOutputTypes.js';
91
74
  export * from './generic/DeleteOptionsInput.js';
92
75
 
76
+ export * from './agents/skip-agent.js';
77
+ export * from './agents/skip-sdk.js';
78
+
93
79
  export * from './resolvers/AskSkipResolver.js';
94
80
  export * from './resolvers/ColorResolver.js';
95
81
  export * from './resolvers/ComponentRegistryResolver.js';
@@ -3,7 +3,7 @@ import { AppContext } from '../types.js';
3
3
  import { LogError, Metadata, RunView, UserInfo, CompositeKey, DatabaseProviderBase } from '@memberjunction/core';
4
4
  import { RequireSystemUser } from '../directives/RequireSystemUser.js';
5
5
  import { QueryCategoryEntity, QueryPermissionEntity } from '@memberjunction/core-entities';
6
- import { QueryResolver } from '../generated/generated.js';
6
+ import { MJQueryResolver } from '../generated/generated.js';
7
7
  import { GetReadOnlyProvider, GetReadWriteProvider } from '../util.js';
8
8
  import { DeleteOptionsInput } from '../generic/DeleteOptionsInput.js';
9
9
  import { QueryEntityExtended } from '@memberjunction/core-entities-server';
@@ -294,7 +294,7 @@ export class DeleteQueryResultType {
294
294
  }
295
295
 
296
296
  @Resolver()
297
- export class QueryResolverExtended extends QueryResolver {
297
+ export class MJQueryResolverExtended extends MJQueryResolver {
298
298
  /**
299
299
  * Creates a new query with the provided attributes. This mutation is restricted to system users only.
300
300
  * @param input - CreateQuerySystemUserInput containing all the query attributes
@@ -373,7 +373,7 @@ export class QueryResolverExtended extends QueryResolver {
373
373
  LogError(err);
374
374
  return {
375
375
  Success: false,
376
- ErrorMessage: `QueryResolverExtended::CreateQuerySystemUser --- Error creating query: ${err instanceof Error ? err.message : String(err)}`
376
+ ErrorMessage: `MJQueryResolverExtended::CreateQuerySystemUser --- Error creating query: ${err instanceof Error ? err.message : String(err)}`
377
377
  };
378
378
  }
379
379
  }
@@ -553,7 +553,7 @@ export class QueryResolverExtended extends QueryResolver {
553
553
  LogError(err);
554
554
  return {
555
555
  Success: false,
556
- ErrorMessage: `QueryResolverExtended::UpdateQuerySystemUser --- Error updating query: ${err instanceof Error ? err.message : String(err)}`
556
+ ErrorMessage: `MJQueryResolverExtended::UpdateQuerySystemUser --- Error updating query: ${err instanceof Error ? err.message : String(err)}`
557
557
  };
558
558
  }
559
559
  }
@@ -578,7 +578,7 @@ export class QueryResolverExtended extends QueryResolver {
578
578
  if (!ID || ID.trim() === '') {
579
579
  return {
580
580
  Success: false,
581
- ErrorMessage: 'QueryResolverExtended::DeleteQuerySystemResolver --- Invalid query ID: ID cannot be null or empty'
581
+ ErrorMessage: 'MJQueryResolverExtended::DeleteQuerySystemResolver --- Invalid query ID: ID cannot be null or empty'
582
582
  };
583
583
  }
584
584
 
@@ -610,7 +610,7 @@ export class QueryResolverExtended extends QueryResolver {
610
610
  LogError(err);
611
611
  return {
612
612
  Success: false,
613
- ErrorMessage: `QueryResolverExtended::DeleteQuerySystemResolver --- Error deleting query: ${err instanceof Error ? err.message : String(err)}`
613
+ ErrorMessage: `MJQueryResolverExtended::DeleteQuerySystemResolver --- Error deleting query: ${err instanceof Error ? err.message : String(err)}`
614
614
  };
615
615
  }
616
616
  }
@@ -1,13 +1,13 @@
1
1
  import { EntityPermissionType, IRunViewProvider } from '@memberjunction/core';
2
2
  import { AppContext } from '../types.js';
3
3
  import { Arg, Ctx, Query, Resolver, InputType, Field } from 'type-graphql';
4
- import { Entity_, EntityResolverBase } from '../generated/generated.js';
4
+ import { MJEntity_, MJEntityResolverBase } from '../generated/generated.js';
5
5
  import sql from 'mssql';
6
6
  import { GetReadOnlyProvider } from '../util.js';
7
7
 
8
- @Resolver(Entity_)
9
- export class EntityResolver extends EntityResolverBase {
10
- @Query(() => [Entity_])
8
+ @Resolver(MJEntity_)
9
+ export class EntityResolver extends MJEntityResolverBase {
10
+ @Query(() => [MJEntity_])
11
11
  async EntitiesBySchemas(
12
12
  @Ctx() { providers, userPayload }: AppContext,
13
13
  @Arg('IncludeSchemas', () => [String], { nullable: true }) IncludeSchemas?: string[],
@@ -2,13 +2,13 @@ import { CompositeKey, EntityDeleteOptions, EntityPermissionType, EntitySaveOpti
2
2
  import { FileCategoryEntity, FileEntity } from '@memberjunction/core-entities';
3
3
  import { AppContext, Arg, Ctx, DeleteOptionsInput, Int, Mutation } from '@memberjunction/server';
4
4
  import { mj_core_schema } from '../config.js';
5
- import { FileCategoryResolver as FileCategoryResolverBase, FileCategory_ } from '../generated/generated.js';
5
+ import { MJFileCategoryResolver as FileCategoryResolverBase, MJFileCategory_ } from '../generated/generated.js';
6
6
  import sql from 'mssql';
7
7
  import { SQLServerDataProvider } from '@memberjunction/sqlserver-dataprovider';
8
8
  import { GetReadWriteProvider } from '../util.js';
9
9
 
10
10
  export class FileResolver extends FileCategoryResolverBase {
11
- @Mutation(() => FileCategory_)
11
+ @Mutation(() => MJFileCategory_)
12
12
  async DeleteFileCategory(
13
13
  @Arg('ID', () => String) ID: string,
14
14
  @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput,
@@ -17,7 +17,7 @@ import {
17
17
  Root,
18
18
  } from '@memberjunction/server';
19
19
  import { createDownloadUrl, createUploadUrl, deleteObject, moveObject } from '@memberjunction/storage';
20
- import { CreateFileInput, FileResolver as FileResolverBase, File_, UpdateFileInput } from '../generated/generated.js';
20
+ import { CreateMJFileInput, MJFileResolver as FileResolverBase, MJFile_, UpdateMJFileInput } from '../generated/generated.js';
21
21
  import { FieldMapper } from '@memberjunction/graphql-dataprovider';
22
22
  import { GetReadOnlyProvider } from '../util.js';
23
23
 
@@ -29,8 +29,8 @@ export class CreateUploadURLInput {
29
29
 
30
30
  @ObjectType()
31
31
  export class CreateFilePayload {
32
- @Field(() => File_)
33
- File: File_;
32
+ @Field(() => MJFile_)
33
+ File: MJFile_;
34
34
  @Field(() => String)
35
35
  UploadUrl: string;
36
36
  @Field(() => Boolean)
@@ -38,16 +38,16 @@ export class CreateFilePayload {
38
38
  }
39
39
 
40
40
  @ObjectType()
41
- export class FileExt extends File_ {
41
+ export class FileExt extends MJFile_ {
42
42
  @Field(() => String)
43
43
  DownloadUrl: string;
44
44
  }
45
45
 
46
- @Resolver(File_)
46
+ @Resolver(MJFile_)
47
47
  export class FileResolver extends FileResolverBase {
48
48
  @Mutation(() => CreateFilePayload)
49
49
  async CreateFile(
50
- @Arg('input', () => CreateFileInput) input: CreateFileInput,
50
+ @Arg('input', () => CreateMJFileInput) input: CreateMJFileInput,
51
51
  @Ctx() context: AppContext,
52
52
  @PubSub() pubSub: PubSubEngine
53
53
  ) {
@@ -86,7 +86,7 @@ export class FileResolver extends FileResolverBase {
86
86
  }
87
87
 
88
88
  @FieldResolver(() => String)
89
- async DownloadUrl(@Root() file: File_, @Ctx() { userPayload }: AppContext) {
89
+ async DownloadUrl(@Root() file: MJFile_, @Ctx() { userPayload }: AppContext) {
90
90
  const md = new Metadata();
91
91
  const user = this.GetUserFromPayload(userPayload);
92
92
  const fileEntity = await md.GetEntityObject<FileEntity>('Files', user);
@@ -100,9 +100,9 @@ export class FileResolver extends FileResolverBase {
100
100
  return url;
101
101
  }
102
102
 
103
- @Mutation(() => File_)
103
+ @Mutation(() => MJFile_)
104
104
  async UpdateFile(
105
- @Arg('input', () => UpdateFileInput) input: UpdateFileInput,
105
+ @Arg('input', () => UpdateMJFileInput) input: UpdateMJFileInput,
106
106
  @Ctx() context: AppContext,
107
107
  @PubSub() pubSub: PubSubEngine
108
108
  ) {
@@ -124,11 +124,11 @@ export class FileResolver extends FileResolverBase {
124
124
  }
125
125
  }
126
126
 
127
- const updatedFile = await super.UpdateFile(input, context, pubSub);
127
+ const updatedFile = await super.UpdateMJFile(input, context, pubSub);
128
128
  return updatedFile;
129
129
  }
130
130
 
131
- @Mutation(() => File_)
131
+ @Mutation(() => MJFile_)
132
132
  async DeleteFile(
133
133
  @Arg('ID', () => String) ID: string,
134
134
  @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput,
@@ -152,6 +152,6 @@ export class FileResolver extends FileResolverBase {
152
152
  await deleteObject(providerEntity, fileEntity.ProviderKey ?? fileEntity.Name);
153
153
  }
154
154
 
155
- return super.DeleteFile(ID, options, context, pubSub);
155
+ return super.DeleteMJFile(ID, options, context, pubSub);
156
156
  }
157
157
  }
@@ -10,12 +10,11 @@ import {
10
10
  import { AppContext } from '../types.js';
11
11
  import { UserCache } from '@memberjunction/sqlserver-dataprovider';
12
12
 
13
- //load the default vectorDB and embedding model
14
- import { LoadMistralEmbedding } from '@memberjunction/ai-mistral';
13
+ //load the default vectorDB
15
14
  import { LoadPineconeVectorDB } from '@memberjunction/ai-vectors-pinecone';
16
15
  import { CompositeKeyInputType, CompositeKeyOutputType, KeyValuePairOutputType } from '../generic/KeyInputOutputTypes.js';
17
16
  import { GetReadOnlyProvider } from '../util.js';
18
- LoadMistralEmbedding();
17
+ // AI provider loading now handled by @memberjunction/aiengine
19
18
  LoadPineconeVectorDB();
20
19
 
21
20
  @InputType()
@@ -9,6 +9,7 @@ import { ResolverBase } from '../generic/ResolverBase.js';
9
9
  import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
10
10
  import { RequireSystemUser } from '../directives/RequireSystemUser.js';
11
11
  import { GetReadWriteProvider } from '../util.js';
12
+ import { SafeJSONParse } from '@memberjunction/global';
12
13
 
13
14
  @ObjectType()
14
15
  export class AIAgentRunResult {
@@ -312,6 +313,7 @@ export class RunAIAgentResolver extends ResolverBase {
312
313
  sessionId: string,
313
314
  pubSub: PubSubEngine,
314
315
  data?: string,
316
+ payload?: string,
315
317
  templateData?: string,
316
318
  lastRunId?: string,
317
319
  autoPopulateLastRunPayload?: boolean,
@@ -356,6 +358,7 @@ export class RunAIAgentResolver extends ResolverBase {
356
358
  const result = await agentRunner.RunAgent({
357
359
  agent: agentEntity,
358
360
  conversationMessages: parsedMessages,
361
+ payload: payload ? SafeJSONParse(payload) : undefined,
359
362
  contextUser: currentUser,
360
363
  onProgress: this.createProgressCallback(pubSub, sessionId, userPayload, agentRunRef),
361
364
  onStreaming: this.createStreamingCallback(pubSub, sessionId, userPayload, agentRunRef),
@@ -464,6 +467,7 @@ export class RunAIAgentResolver extends ResolverBase {
464
467
  @Arg('sessionId') sessionId: string,
465
468
  @PubSub() pubSub: PubSubEngine,
466
469
  @Arg('data', { nullable: true }) data?: string,
470
+ @Arg('payload', { nullable: true }) payload?: string,
467
471
  @Arg('templateData', { nullable: true }) templateData?: string,
468
472
  @Arg('lastRunId', { nullable: true }) lastRunId?: string,
469
473
  @Arg('autoPopulateLastRunPayload', { nullable: true }) autoPopulateLastRunPayload?: boolean,
@@ -479,6 +483,7 @@ export class RunAIAgentResolver extends ResolverBase {
479
483
  sessionId,
480
484
  pubSub,
481
485
  data,
486
+ payload,
482
487
  templateData,
483
488
  lastRunId,
484
489
  autoPopulateLastRunPayload,
@@ -500,6 +505,7 @@ export class RunAIAgentResolver extends ResolverBase {
500
505
  @Arg('sessionId') sessionId: string,
501
506
  @PubSub() pubSub: PubSubEngine,
502
507
  @Arg('data', { nullable: true }) data?: string,
508
+ @Arg('payload', { nullable: true }) payload?: string,
503
509
  @Arg('templateData', { nullable: true }) templateData?: string,
504
510
  @Arg('lastRunId', { nullable: true }) lastRunId?: string,
505
511
  @Arg('autoPopulateLastRunPayload', { nullable: true }) autoPopulateLastRunPayload?: boolean,
@@ -515,6 +521,7 @@ export class RunAIAgentResolver extends ResolverBase {
515
521
  sessionId,
516
522
  pubSub,
517
523
  data,
524
+ payload,
518
525
  templateData,
519
526
  lastRunId,
520
527
  autoPopulateLastRunPayload,
@@ -1,9 +1,8 @@
1
1
  import { Resolver, Mutation, Arg, Ctx, ObjectType, Field } from 'type-graphql';
2
2
  import { AppContext, UserPayload } from '../types.js';
3
3
  import { LogError, LogStatus, Metadata, RunView } from '@memberjunction/core';
4
- import { TemplateContentEntity } from '@memberjunction/core-entities';
4
+ import { TemplateContentEntity, TemplateEntityExtended } from '@memberjunction/core-entities';
5
5
  import { TemplateEngineServer } from '@memberjunction/templates';
6
- import { TemplateEntityExtended } from '@memberjunction/templates-base-types';
7
6
  import { ResolverBase } from '../generic/ResolverBase.js';
8
7
  import { GetReadWriteProvider } from '../util.js';
9
8
 
@@ -0,0 +1,142 @@
1
+ import { Resolver, Mutation, Arg, Ctx, ObjectType, Field, PubSub, PubSubEngine } from 'type-graphql';
2
+ import { AppContext } from '../types.js';
3
+ import { LogError, LogStatus } from '@memberjunction/core';
4
+ import { ResolverBase } from '../generic/ResolverBase.js';
5
+ import { TaskOrchestrator, TaskGraphResponse, TaskExecutionResult } from '../services/TaskOrchestrator.js';
6
+
7
+ @ObjectType()
8
+ export class TaskExecutionResultType {
9
+ @Field()
10
+ taskId: string;
11
+
12
+ @Field()
13
+ success: boolean;
14
+
15
+ @Field({ nullable: true })
16
+ output?: string;
17
+
18
+ @Field({ nullable: true })
19
+ error?: string;
20
+ }
21
+
22
+ @ObjectType()
23
+ export class ExecuteTaskGraphResult {
24
+ @Field()
25
+ success: boolean;
26
+
27
+ @Field({ nullable: true })
28
+ errorMessage?: string;
29
+
30
+ @Field(() => [TaskExecutionResultType])
31
+ results: TaskExecutionResultType[];
32
+ }
33
+
34
+ /**
35
+ * TaskOrchestrationResolver handles multi-step task orchestration.
36
+ * This resolver is called when the Conversation Manager returns a task graph
37
+ * for complex workflows that require multiple agents working in sequence or parallel.
38
+ */
39
+ @Resolver()
40
+ export class TaskOrchestrationResolver extends ResolverBase {
41
+ /**
42
+ * Execute a task graph from the Conversation Manager.
43
+ * This creates tasks in the database, manages dependencies, and executes them in proper order.
44
+ *
45
+ * @param taskGraphJson - JSON string containing the task graph from Conversation Manager
46
+ * @param conversationDetailId - ID of the conversation detail that triggered this workflow
47
+ * @param environmentId - Environment ID for the tasks
48
+ */
49
+ @Mutation(() => ExecuteTaskGraphResult)
50
+ async ExecuteTaskGraph(
51
+ @Arg('taskGraphJson') taskGraphJson: string,
52
+ @Arg('conversationDetailId') conversationDetailId: string,
53
+ @Arg('environmentId') environmentId: string,
54
+ @Arg('sessionId') sessionId: string,
55
+ @PubSub() pubSub: PubSubEngine,
56
+ @Ctx() { userPayload }: AppContext
57
+ ): Promise<ExecuteTaskGraphResult> {
58
+ try {
59
+ LogStatus(`=== EXECUTING TASK GRAPH FOR CONVERSATION: ${conversationDetailId} ===`);
60
+
61
+ // Parse task graph
62
+ const taskGraph: TaskGraphResponse = JSON.parse(taskGraphJson);
63
+
64
+ // Validate task graph
65
+ if (!taskGraph.workflowName || !taskGraph.tasks || taskGraph.tasks.length === 0) {
66
+ throw new Error('Invalid task graph: must have workflowName and at least one task');
67
+ }
68
+
69
+ // Get current user
70
+ const currentUser = this.GetUserFromPayload(userPayload);
71
+ if (!currentUser) {
72
+ throw new Error('Unable to determine current user');
73
+ }
74
+
75
+ LogStatus(`Workflow: ${taskGraph.workflowName} (${taskGraph.tasks.length} tasks)`);
76
+ if (taskGraph.reasoning) {
77
+ LogStatus(`Reasoning: ${taskGraph.reasoning}`);
78
+ }
79
+
80
+ // Create task orchestrator with PubSub for progress updates
81
+ const orchestrator = new TaskOrchestrator(currentUser, pubSub, sessionId, userPayload);
82
+
83
+ // Create parent task and child tasks with dependencies
84
+ const { parentTaskId, taskIdMap } = await orchestrator.createTasksFromGraph(
85
+ taskGraph,
86
+ conversationDetailId,
87
+ environmentId
88
+ );
89
+
90
+ LogStatus(`Created parent task ${parentTaskId} with ${taskIdMap.size} child tasks`);
91
+
92
+ // Execute tasks in proper order
93
+ const results = await orchestrator.executeTasksForParent(
94
+ parentTaskId
95
+ );
96
+
97
+ // Log results
98
+ const successCount = results.filter(r => r.success).length;
99
+ LogStatus(`Completed ${successCount} of ${results.length} tasks successfully`);
100
+
101
+ for (const result of results) {
102
+ if (result.success) {
103
+ LogStatus(`✅ Task ${result.taskId} completed successfully`);
104
+ } else {
105
+ LogError(`❌ Task ${result.taskId} failed: ${result.error}`);
106
+ }
107
+ }
108
+
109
+ // Convert results to GraphQL types
110
+ const graphqlResults: TaskExecutionResultType[] = results.map(r => ({
111
+ taskId: r.taskId,
112
+ success: r.success,
113
+ output: r.output ? JSON.stringify(r.output) : undefined,
114
+ error: r.error
115
+ }));
116
+
117
+ LogStatus(`=== TASK GRAPH EXECUTION COMPLETE ===`);
118
+
119
+ const result = {
120
+ success: true,
121
+ results: graphqlResults
122
+ };
123
+
124
+ LogStatus(`Returning ExecuteTaskGraph result: ${JSON.stringify({
125
+ success: result.success,
126
+ resultsCount: result.results.length,
127
+ firstResult: result.results[0]
128
+ })}`);
129
+
130
+ return result;
131
+
132
+ } catch (error) {
133
+ LogError(`Task graph execution failed:`, undefined, error);
134
+
135
+ return {
136
+ success: false,
137
+ errorMessage: (error as Error).message || 'Unknown error occurred',
138
+ results: []
139
+ };
140
+ }
141
+ }
142
+ }
@@ -15,7 +15,7 @@ import {
15
15
  } from '@memberjunction/server';
16
16
  import { UserCache } from '@memberjunction/sqlserver-dataprovider';
17
17
 
18
- import { UserFavorite_, UserFavoriteResolverBase } from '../generated/generated.js';
18
+ import { MJUserFavorite_, MJUserFavoriteResolverBase } from '../generated/generated.js';
19
19
  import { GetReadOnlyProvider } from '../util.js';
20
20
 
21
21
  //****************************************************************************
@@ -66,15 +66,15 @@ export class UserFavoriteResult {
66
66
  Success: boolean;
67
67
  }
68
68
 
69
- @Resolver(UserFavorite_)
70
- export class UserFavoriteResolver extends UserFavoriteResolverBase {
71
- @Query(() => [UserFavorite_])
69
+ @Resolver(MJUserFavorite_)
70
+ export class UserFavoriteResolver extends MJUserFavoriteResolverBase {
71
+ @Query(() => [MJUserFavorite_])
72
72
  async UserFavoritesByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() { providers, userPayload }: AppContext) {
73
73
  const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
74
74
  return await this.findBy(provider, 'User Favorites', { UserID }, userPayload.userRecord);
75
75
  }
76
76
 
77
- @Query(() => [UserFavorite_])
77
+ @Query(() => [MJUserFavorite_])
78
78
  async UserFavoriteSearchByParams(@Arg('params', () => Int) params: UserFavoriteSearchParams, @Ctx() { providers, userPayload }: AppContext) {
79
79
  const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
80
80
  return await this.findBy(provider, 'User Favorites', params, userPayload.userRecord);
@@ -1,31 +1,31 @@
1
1
  import { AppContext, Arg, Ctx, Int, Query, Resolver } from '@memberjunction/server';
2
- import { User_, UserResolverBase } from '../generated/generated.js';
2
+ import { MJUser_, MJUserResolverBase } from '../generated/generated.js';
3
3
  import { GetReadOnlyProvider } from '../util.js';
4
4
 
5
- @Resolver(User_)
6
- export class UserResolver extends UserResolverBase {
7
- @Query(() => User_)
5
+ @Resolver(MJUser_)
6
+ export class UserResolver extends MJUserResolverBase {
7
+ @Query(() => MJUser_)
8
8
  async CurrentUser(@Ctx() context: AppContext) {
9
9
  const result = await this.UserByEmail(context.userPayload.email, context);
10
10
  console.log('CurrentUser', result);
11
11
  return result;
12
12
  }
13
13
 
14
- @Query(() => User_)
14
+ @Query(() => MJUser_)
15
15
  async UserByID(@Arg('ID', () => Int) ID: number, @Ctx() { providers, userPayload }: AppContext) {
16
16
  const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
17
17
  const retVal = super.safeFirstArrayElement(await this.findBy(provider, 'Users', { ID }, userPayload.userRecord));
18
18
  return this.MapFieldNamesToCodeNames('Users', retVal);
19
19
  }
20
20
 
21
- @Query(() => User_)
21
+ @Query(() => MJUser_)
22
22
  async UserByEmployeeID(@Arg('EmployeeID', () => Int) EmployeeID: number, @Ctx() { providers, userPayload }: AppContext) {
23
23
  const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
24
24
  const retVal = super.safeFirstArrayElement(await this.findBy(provider, 'Users', { EmployeeID }, userPayload.userRecord));
25
25
  return this.MapFieldNamesToCodeNames('Users', retVal);
26
26
  }
27
27
 
28
- @Query(() => User_)
28
+ @Query(() => MJUser_)
29
29
  async UserByEmail(@Arg('Email', () => String) Email: string, @Ctx() { providers, userPayload }: AppContext) {
30
30
  // const searchEmail = userEmailMap[Email] ?? Email;
31
31
  const searchEmail = Email;
@@ -1,20 +1,20 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { EntitySaveOptions, Metadata } from '@memberjunction/core';
3
3
  import { AppContext, Arg, Ctx, Int, Query, Resolver, UserPayload } from '@memberjunction/server';
4
- import { UserView_, UserViewResolverBase } from '../generated/generated.js';
4
+ import { MJUserView_, MJUserViewResolverBase } from '../generated/generated.js';
5
5
  import { UserResolver } from './UserResolver.js';
6
6
  import { UserViewEntity, UserViewEntityExtended } from '@memberjunction/core-entities';
7
7
  import { GetReadOnlyProvider } from '../util.js';
8
8
 
9
- @Resolver(UserView_)
10
- export class UserViewResolver extends UserViewResolverBase {
11
- @Query(() => [UserView_])
9
+ @Resolver(MJUserView_)
10
+ export class UserViewResolver extends MJUserViewResolverBase {
11
+ @Query(() => [MJUserView_])
12
12
  async UserViewsByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() { providers, userPayload }: AppContext) {
13
13
  const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
14
14
  return await this.findBy(provider, 'User Views', { UserID }, userPayload.userRecord);
15
15
  }
16
16
 
17
- @Query(() => [UserView_])
17
+ @Query(() => [MJUserView_])
18
18
  async DefaultViewByUserAndEntity(
19
19
  @Arg('UserID', () => Int) UserID: number,
20
20
  @Arg('EntityID', () => Int) EntityID: number,
@@ -24,7 +24,7 @@ export class UserViewResolver extends UserViewResolverBase {
24
24
  return await this.findBy(provider, 'User Views', { UserID, EntityID, IsDefault: true }, userPayload.userRecord);
25
25
  }
26
26
 
27
- @Query(() => [UserView_])
27
+ @Query(() => [MJUserView_])
28
28
  async CurrentUserDefaultViewByEntityID(@Arg('EntityID', () => Int) EntityID: number, @Ctx() context: AppContext) {
29
29
  const provider = GetReadOnlyProvider(context.providers, {allowFallbackToReadWrite: true})
30
30
  return await this.findBy(provider, 'User Views', {
@@ -40,13 +40,13 @@ export class UserViewResolver extends UserViewResolverBase {
40
40
  return user.ID;
41
41
  }
42
42
 
43
- @Query(() => [UserView_])
43
+ @Query(() => [MJUserView_])
44
44
  async CurrentUserUserViewsByEntityID(@Arg('EntityID', () => Int) EntityID: number, @Ctx() context: AppContext) {
45
45
  const provider = GetReadOnlyProvider(context.providers, {allowFallbackToReadWrite: true})
46
46
  return this.findBy(provider, 'User Views', { UserID: await this.getCurrentUserID(context), EntityID}, context.userPayload.userRecord);
47
47
  }
48
48
 
49
- @Query(() => [UserView_])
49
+ @Query(() => [MJUserView_])
50
50
  async UpdateWhereClause(@Arg('ID', () => String) ID: string, @Ctx() { userPayload, providers }: AppContext) {
51
51
  // in this query we want to update the uesrView record in the DB with a new where clause
52
52
  // this should normally not be a factor but we have this exposed in the GraphQL API so that