@memberjunction/server 2.43.0 → 2.44.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.
@@ -0,0 +1,169 @@
1
+ import { Resolver, Mutation, Arg, Ctx, ObjectType, Field } from 'type-graphql';
2
+ import { UserPayload } from '../types.js';
3
+ import { LogError, LogStatus, Metadata } from '@memberjunction/core';
4
+ import { AIPromptEntity } from '@memberjunction/core-entities';
5
+ import { AIPromptRunner, AIPromptParams } from '@memberjunction/ai-prompts';
6
+ import { ResolverBase } from '../generic/ResolverBase.js';
7
+
8
+ @ObjectType()
9
+ export class AIPromptRunResult {
10
+ @Field()
11
+ success: boolean;
12
+
13
+ @Field({ nullable: true })
14
+ output?: string;
15
+
16
+ @Field({ nullable: true })
17
+ parsedResult?: string;
18
+
19
+ @Field({ nullable: true })
20
+ error?: string;
21
+
22
+ @Field({ nullable: true })
23
+ executionTimeMs?: number;
24
+
25
+ @Field({ nullable: true })
26
+ tokensUsed?: number;
27
+
28
+ @Field({ nullable: true })
29
+ promptRunId?: string;
30
+
31
+ @Field({ nullable: true })
32
+ rawResult?: string;
33
+
34
+ @Field({ nullable: true })
35
+ validationResult?: string;
36
+ }
37
+
38
+ @Resolver()
39
+ export class RunAIPromptResolver extends ResolverBase {
40
+ @Mutation(() => AIPromptRunResult)
41
+ async RunAIPrompt(
42
+ @Arg('promptId') promptId: string,
43
+ @Ctx() { userPayload }: { userPayload: UserPayload },
44
+ @Arg('data', { nullable: true }) data?: string,
45
+ @Arg('modelId', { nullable: true }) modelId?: string,
46
+ @Arg('vendorId', { nullable: true }) vendorId?: string,
47
+ @Arg('configurationId', { nullable: true }) configurationId?: string,
48
+ @Arg('skipValidation', { nullable: true }) skipValidation?: boolean,
49
+ @Arg('templateData', { nullable: true }) templateData?: string
50
+ ): Promise<AIPromptRunResult> {
51
+ const startTime = Date.now();
52
+
53
+ try {
54
+ LogStatus(`=== RUNNING AI PROMPT FOR ID: ${promptId} ===`);
55
+
56
+ // Parse data contexts (JSON strings)
57
+ let parsedData = {};
58
+ let parsedTemplateData = {};
59
+
60
+ if (data) {
61
+ try {
62
+ parsedData = JSON.parse(data);
63
+ } catch (parseError) {
64
+ return {
65
+ success: false,
66
+ error: `Invalid JSON in data: ${(parseError as Error).message}`,
67
+ executionTimeMs: Date.now() - startTime
68
+ };
69
+ }
70
+ }
71
+
72
+ if (templateData) {
73
+ try {
74
+ parsedTemplateData = JSON.parse(templateData);
75
+ } catch (parseError) {
76
+ return {
77
+ success: false,
78
+ error: `Invalid JSON in template data: ${(parseError as Error).message}`,
79
+ executionTimeMs: Date.now() - startTime
80
+ };
81
+ }
82
+ }
83
+
84
+ // Get current user from payload
85
+ const currentUser = this.GetUserFromPayload(userPayload);
86
+ if (!currentUser) {
87
+ return {
88
+ success: false,
89
+ error: 'Unable to determine current user',
90
+ executionTimeMs: Date.now() - startTime
91
+ };
92
+ }
93
+
94
+ const md = new Metadata();
95
+
96
+ // Load the AI prompt entity
97
+ const promptEntity = await md.GetEntityObject<AIPromptEntity>('AI Prompts', currentUser);
98
+ await promptEntity.Load(promptId);
99
+
100
+ if (!promptEntity.IsSaved) {
101
+ return {
102
+ success: false,
103
+ error: `AI Prompt with ID ${promptId} not found`,
104
+ executionTimeMs: Date.now() - startTime
105
+ };
106
+ }
107
+
108
+ // Check if prompt is active
109
+ if (promptEntity.Status !== 'Active') {
110
+ return {
111
+ success: false,
112
+ error: `AI Prompt "${promptEntity.Name}" is not active (Status: ${promptEntity.Status})`,
113
+ executionTimeMs: Date.now() - startTime
114
+ };
115
+ }
116
+
117
+ // Create AI prompt runner and execute
118
+ const promptRunner = new AIPromptRunner();
119
+
120
+ // Build execution parameters
121
+ const promptParams = new AIPromptParams();
122
+ promptParams.prompt = promptEntity;
123
+ promptParams.data = parsedData;
124
+ promptParams.templateData = parsedTemplateData;
125
+ promptParams.modelId = modelId;
126
+ promptParams.vendorId = vendorId;
127
+ promptParams.configurationId = configurationId;
128
+ promptParams.contextUser = currentUser;
129
+ promptParams.skipValidation = skipValidation || false;
130
+
131
+ // Execute the prompt
132
+ const result = await promptRunner.ExecutePrompt(promptParams);
133
+
134
+ const executionTime = Date.now() - startTime;
135
+
136
+ if (result.success) {
137
+ LogStatus(`=== AI PROMPT RUN COMPLETED FOR: ${promptEntity.Name} (${executionTime}ms) ===`);
138
+
139
+ return {
140
+ success: true,
141
+ output: result.rawResult,
142
+ parsedResult: typeof result.result === 'string' ? result.result : JSON.stringify(result.result),
143
+ rawResult: result.rawResult,
144
+ executionTimeMs: executionTime,
145
+ tokensUsed: result.tokensUsed,
146
+ promptRunId: result.promptRun?.ID,
147
+ validationResult: result.validationResult ? JSON.stringify(result.validationResult) : undefined
148
+ };
149
+ } else {
150
+ LogError(`AI Prompt run failed for ${promptEntity.Name}: ${result.errorMessage}`);
151
+ return {
152
+ success: false,
153
+ error: result.errorMessage,
154
+ executionTimeMs: executionTime,
155
+ promptRunId: result.promptRun?.ID
156
+ };
157
+ }
158
+
159
+ } catch (error) {
160
+ const executionTime = Date.now() - startTime;
161
+ LogError(`AI Prompt run failed:`, undefined, error);
162
+ return {
163
+ success: false,
164
+ error: (error as Error).message || 'Unknown error occurred',
165
+ executionTimeMs: executionTime
166
+ };
167
+ }
168
+ }
169
+ }
@@ -0,0 +1,130 @@
1
+ import { Resolver, Mutation, Arg, Ctx, ObjectType, Field } from 'type-graphql';
2
+ import { UserPayload } from '../types.js';
3
+ import { LogError, LogStatus, Metadata, RunView } from '@memberjunction/core';
4
+ import { TemplateContentEntity } from '@memberjunction/core-entities';
5
+ import { TemplateEngineServer } from '@memberjunction/templates';
6
+ import { TemplateEntityExtended } from '@memberjunction/templates-base-types';
7
+ import { ResolverBase } from '../generic/ResolverBase.js';
8
+
9
+ @ObjectType()
10
+ export class TemplateRunResult {
11
+ @Field()
12
+ success: boolean;
13
+
14
+ @Field({ nullable: true })
15
+ output?: string;
16
+
17
+ @Field({ nullable: true })
18
+ error?: string;
19
+
20
+ @Field({ nullable: true })
21
+ executionTimeMs?: number;
22
+ }
23
+
24
+ @Resolver()
25
+ export class RunTemplateResolver extends ResolverBase {
26
+ @Mutation(() => TemplateRunResult)
27
+ async RunTemplate(
28
+ @Arg('templateId') templateId: string,
29
+ @Ctx() { userPayload }: { userPayload: UserPayload },
30
+ @Arg('contextData', { nullable: true }) contextData?: string
31
+ ): Promise<TemplateRunResult> {
32
+ const startTime = Date.now();
33
+
34
+ try {
35
+ LogStatus(`=== RUNNING TEMPLATE FOR ID: ${templateId} ===`);
36
+
37
+ // Parse context data (JSON string)
38
+ let data = {};
39
+ if (contextData) {
40
+ try {
41
+ data = JSON.parse(contextData);
42
+ } catch (parseError) {
43
+ return {
44
+ success: false,
45
+ error: `Invalid JSON in context data: ${(parseError as Error).message}`,
46
+ executionTimeMs: Date.now() - startTime
47
+ };
48
+ }
49
+ }
50
+
51
+ // Get current user from payload
52
+ const currentUser = this.GetUserFromPayload(userPayload);
53
+ if (!currentUser) {
54
+ return {
55
+ success: false,
56
+ error: 'Unable to determine current user',
57
+ executionTimeMs: Date.now() - startTime
58
+ };
59
+ }
60
+
61
+ const md = new Metadata();
62
+
63
+ // Load the template entity
64
+ const templateEntity = await md.GetEntityObject<TemplateEntityExtended>('Templates', currentUser);
65
+ await templateEntity.Load(templateId);
66
+
67
+ if (!templateEntity.IsSaved) {
68
+ return {
69
+ success: false,
70
+ error: `Template with ID ${templateId} not found`,
71
+ executionTimeMs: Date.now() - startTime
72
+ };
73
+ }
74
+
75
+ // Load template content (get the first/highest priority content)
76
+ const rv = new RunView();
77
+ const templateContentResult = await rv.RunView<TemplateContentEntity>({
78
+ EntityName: 'Template Contents',
79
+ ExtraFilter: `TemplateID = '${templateId}'`,
80
+ OrderBy: 'Priority ASC',
81
+ MaxRows: 1,
82
+ ResultType: 'entity_object'
83
+ }, currentUser);
84
+
85
+ if (!templateContentResult.Results || templateContentResult.Results.length === 0) {
86
+ return {
87
+ success: false,
88
+ error: `No template content found for template ${templateEntity.Name}`,
89
+ executionTimeMs: Date.now() - startTime
90
+ };
91
+ }
92
+
93
+ // Configure and render the template
94
+ await TemplateEngineServer.Instance.Config(true /*always refresh to get latest templates*/, currentUser);
95
+ const result = await TemplateEngineServer.Instance.RenderTemplate(
96
+ templateEntity,
97
+ templateContentResult.Results[0],
98
+ data,
99
+ true // skip validation for execution
100
+ );
101
+
102
+ const executionTime = Date.now() - startTime;
103
+
104
+ if (result.Success) {
105
+ LogStatus(`=== TEMPLATE RUN COMPLETED FOR: ${templateEntity.Name} (${executionTime}ms) ===`);
106
+ return {
107
+ success: true,
108
+ output: result.Output,
109
+ executionTimeMs: executionTime
110
+ };
111
+ } else {
112
+ LogError(`Template run failed for ${templateEntity.Name}: ${result.Message}`);
113
+ return {
114
+ success: false,
115
+ error: result.Message,
116
+ executionTimeMs: executionTime
117
+ };
118
+ }
119
+
120
+ } catch (error) {
121
+ const executionTime = Date.now() - startTime;
122
+ LogError(`Template run failed:`, undefined, error);
123
+ return {
124
+ success: false,
125
+ error: (error as Error).message || 'Unknown error occurred',
126
+ executionTimeMs: executionTime
127
+ };
128
+ }
129
+ }
130
+ }