@memberjunction/server 5.0.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/entitySubclasses/{entityPermissions.server.d.ts → MJEntityPermissionEntityServer.server.d.ts} +2 -2
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.d.ts.map +1 -0
- package/dist/entitySubclasses/{entityPermissions.server.js → MJEntityPermissionEntityServer.server.js} +9 -9
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.js.map +1 -0
- package/dist/generated/generated.d.ts +213 -26
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +1183 -124
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +2 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts +28 -0
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -0
- package/dist/resolvers/AdhocQueryResolver.js +140 -0
- package/dist/resolvers/AdhocQueryResolver.js.map +1 -0
- package/dist/resolvers/CreateQueryResolver.js +2 -2
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/services/TaskOrchestrator.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +52 -52
- package/src/__tests__/AdhocQueryResolver.test.ts +175 -0
- package/src/entitySubclasses/{entityPermissions.server.ts → MJEntityPermissionEntityServer.server.ts} +3 -3
- package/src/generated/generated.ts +827 -99
- package/src/generic/ResolverBase.ts +9 -9
- package/src/generic/RunViewResolver.ts +4 -4
- package/src/index.ts +1 -1
- package/src/resolvers/AdhocQueryResolver.ts +126 -0
- package/src/resolvers/CreateQueryResolver.ts +5 -5
- package/src/resolvers/RunAIAgentResolver.ts +4 -4
- package/src/resolvers/RunAIPromptResolver.ts +7 -7
- package/src/resolvers/RunTemplateResolver.ts +2 -2
- package/src/resolvers/UserViewResolver.ts +2 -2
- package/src/services/TaskOrchestrator.ts +5 -5
- package/src/types.ts +2 -2
- package/dist/apolloServer/TransactionPlugin.d.ts +0 -4
- package/dist/apolloServer/TransactionPlugin.d.ts.map +0 -1
- package/dist/apolloServer/TransactionPlugin.js +0 -46
- package/dist/apolloServer/TransactionPlugin.js.map +0 -1
- package/dist/auth/__tests__/backward-compatibility.test.d.ts +0 -2
- package/dist/auth/__tests__/backward-compatibility.test.d.ts.map +0 -1
- package/dist/auth/__tests__/backward-compatibility.test.js +0 -135
- package/dist/auth/__tests__/backward-compatibility.test.js.map +0 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +0 -1
- package/dist/entitySubclasses/entityPermissions.server.js.map +0 -1
- package/dist/resolvers/AskSkipResolver.d.ts +0 -123
- package/dist/resolvers/AskSkipResolver.d.ts.map +0 -1
- package/dist/resolvers/AskSkipResolver.js +0 -1788
- package/dist/resolvers/AskSkipResolver.js.map +0 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts +0 -4
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +0 -1
- package/dist/scheduler/LearningCycleScheduler.js +0 -4
- package/dist/scheduler/LearningCycleScheduler.js.map +0 -1
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
RunViewResult,
|
|
18
18
|
UserInfo,
|
|
19
19
|
} from '@memberjunction/core';
|
|
20
|
-
import { MJAuditLogEntity, MJErrorLogEntity,
|
|
20
|
+
import { MJAuditLogEntity, MJErrorLogEntity, MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
21
21
|
import { SQLServerDataProvider, UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
22
22
|
import { PubSubEngine, AuthorizationError } from 'type-graphql';
|
|
23
23
|
import { GraphQLError } from 'graphql';
|
|
@@ -274,7 +274,7 @@ export class ResolverBase {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
const rv = provider as any as IRunViewProvider;
|
|
277
|
-
const result = await rv.RunView<
|
|
277
|
+
const result = await rv.RunView<MJUserViewEntityExtended>({
|
|
278
278
|
EntityName: 'MJ: User Views',
|
|
279
279
|
ExtraFilter: "Name='" + viewInput.ViewName + "'",
|
|
280
280
|
}, userPayload.userRecord);
|
|
@@ -319,7 +319,7 @@ export class ResolverBase {
|
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
const contextUser = this.GetUserFromPayload(userPayload);
|
|
322
|
-
const viewInfo = await provider.GetEntityObject<
|
|
322
|
+
const viewInfo = await provider.GetEntityObject<MJUserViewEntityExtended>('MJ: User Views', contextUser);
|
|
323
323
|
await viewInfo.Load(viewInput.ViewID);
|
|
324
324
|
return this.RunViewGenericInternal(
|
|
325
325
|
provider,
|
|
@@ -358,12 +358,12 @@ export class ResolverBase {
|
|
|
358
358
|
const entity = md.Entities.find((e) => e.Name === viewInput.EntityName);
|
|
359
359
|
if (!entity) throw new Error(`Entity ${viewInput.EntityName} not found in metadata`);
|
|
360
360
|
|
|
361
|
-
const viewInfo:
|
|
361
|
+
const viewInfo: MJUserViewEntityExtended = {
|
|
362
362
|
ID: '',
|
|
363
363
|
Entity: viewInput.EntityName,
|
|
364
364
|
EntityID: entity.ID,
|
|
365
365
|
EntityBaseView: entity.BaseView as string,
|
|
366
|
-
} as
|
|
366
|
+
} as MJUserViewEntityExtended; // only providing a few bits of data here, but it's enough to get the view to run
|
|
367
367
|
|
|
368
368
|
return this.RunViewGenericInternal(
|
|
369
369
|
provider,
|
|
@@ -401,12 +401,12 @@ export class ResolverBase {
|
|
|
401
401
|
let params: RunViewGenericParams[] = [];
|
|
402
402
|
for (const viewInput of viewInputs) {
|
|
403
403
|
try {
|
|
404
|
-
let viewInfo:
|
|
404
|
+
let viewInfo: MJUserViewEntityExtended | null = null;
|
|
405
405
|
|
|
406
406
|
if (viewInput.ViewName) {
|
|
407
407
|
viewInfo = this.safeFirstArrayElement(await this.findBy(provider, 'MJ: User Views', { Name: viewInput.ViewName }, userPayload.userRecord));
|
|
408
408
|
} else if (viewInput.ViewID) {
|
|
409
|
-
viewInfo = await provider.GetEntityObject<
|
|
409
|
+
viewInfo = await provider.GetEntityObject<MJUserViewEntityExtended>('MJ: User Views', contextUser);
|
|
410
410
|
await viewInfo.Load(viewInput.ViewID);
|
|
411
411
|
} else if (viewInput.EntityName) {
|
|
412
412
|
const entity = md.Entities.find((e) => e.Name === viewInput.EntityName);
|
|
@@ -420,7 +420,7 @@ export class ResolverBase {
|
|
|
420
420
|
Entity: viewInput.EntityName,
|
|
421
421
|
EntityID: entity.ID,
|
|
422
422
|
EntityBaseView: entity.BaseView,
|
|
423
|
-
} as
|
|
423
|
+
} as MJUserViewEntityExtended;
|
|
424
424
|
} else {
|
|
425
425
|
throw new Error('Unable to determine input type');
|
|
426
426
|
}
|
|
@@ -603,7 +603,7 @@ export class ResolverBase {
|
|
|
603
603
|
*/
|
|
604
604
|
protected async RunViewGenericInternal(
|
|
605
605
|
provider: DatabaseProviderBase,
|
|
606
|
-
viewInfo:
|
|
606
|
+
viewInfo: MJUserViewEntityExtended,
|
|
607
607
|
extraFilter: string,
|
|
608
608
|
orderBy: string,
|
|
609
609
|
userSearchString: string,
|
|
@@ -4,7 +4,7 @@ import { ResolverBase } from './ResolverBase.js';
|
|
|
4
4
|
import { LogError, LogStatus, EntityInfo, RunViewWithCacheCheckResult, RunViewsWithCacheCheckResponse, RunViewWithCacheCheckParams, AggregateResult } from '@memberjunction/core';
|
|
5
5
|
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
|
|
6
6
|
import { GetReadOnlyProvider } from '../util.js';
|
|
7
|
-
import {
|
|
7
|
+
import { MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
8
8
|
import { KeyValuePairOutputType } from './KeyInputOutputTypes.js';
|
|
9
9
|
import { SQLServerDataProvider } from '@memberjunction/sqlserver-dataprovider';
|
|
10
10
|
|
|
@@ -652,7 +652,7 @@ export class RunViewResolver extends ResolverBase {
|
|
|
652
652
|
if (rawData === null)
|
|
653
653
|
return null;
|
|
654
654
|
|
|
655
|
-
const viewInfo = super.safeFirstArrayElement<
|
|
655
|
+
const viewInfo = super.safeFirstArrayElement<MJUserViewEntityExtended>(await super.findBy<MJUserViewEntityExtended>(provider, "MJ: User Views", { Name: input.ViewName }, userPayload.userRecord));
|
|
656
656
|
const entity = provider.Entities.find((e) => e.ID === viewInfo.EntityID);
|
|
657
657
|
const returnData = this.processRawData(rawData.Results, viewInfo.EntityID, entity);
|
|
658
658
|
return {
|
|
@@ -683,7 +683,7 @@ export class RunViewResolver extends ResolverBase {
|
|
|
683
683
|
if (rawData === null)
|
|
684
684
|
return null;
|
|
685
685
|
|
|
686
|
-
const viewInfo = super.safeFirstArrayElement<
|
|
686
|
+
const viewInfo = super.safeFirstArrayElement<MJUserViewEntityExtended>(await super.findBy<MJUserViewEntityExtended>(provider, "MJ: User Views", { ID: input.ViewID }, userPayload.userRecord));
|
|
687
687
|
const entity = provider.Entities.find((e) => e.ID === viewInfo.EntityID);
|
|
688
688
|
const returnData = this.processRawData(rawData.Results, viewInfo.EntityID, entity);
|
|
689
689
|
return {
|
|
@@ -837,7 +837,7 @@ export class RunViewResolver extends ResolverBase {
|
|
|
837
837
|
};
|
|
838
838
|
}
|
|
839
839
|
|
|
840
|
-
const viewInfo = super.safeFirstArrayElement<
|
|
840
|
+
const viewInfo = super.safeFirstArrayElement<MJUserViewEntityExtended>(await super.findBy<MJUserViewEntityExtended>(provider, "MJ: User Views", { ID: input.ViewID }, userPayload.userRecord));
|
|
841
841
|
const entity = provider.Entities.find((e) => e.ID === viewInfo.EntityID);
|
|
842
842
|
const returnData = this.processRawData(rawData.Results, viewInfo.EntityID, entity);
|
|
843
843
|
return {
|
package/src/index.ts
CHANGED
|
@@ -44,7 +44,7 @@ export * from 'type-graphql';
|
|
|
44
44
|
export { NewUserBase } from './auth/newUsers.js';
|
|
45
45
|
export { configInfo, DEFAULT_SERVER_CONFIG } from './config.js';
|
|
46
46
|
export * from './directives/index.js';
|
|
47
|
-
export * from './entitySubclasses/
|
|
47
|
+
export * from './entitySubclasses/MJEntityPermissionEntityServer.server.js';
|
|
48
48
|
export * from './types.js';
|
|
49
49
|
export {
|
|
50
50
|
TokenExpiredError,
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Arg, Ctx, Query, Resolver, Field, Int, InputType } from 'type-graphql';
|
|
2
|
+
import { LogError } from '@memberjunction/core';
|
|
3
|
+
import { SQLExpressionValidator } from '@memberjunction/global';
|
|
4
|
+
import { AppContext } from '../types.js';
|
|
5
|
+
import { GetReadOnlyDataSource } from '../util.js';
|
|
6
|
+
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
7
|
+
import { RunQueryResultType } from './QueryResolver.js';
|
|
8
|
+
import sql from 'mssql';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Input type for executing ad-hoc SQL queries directly.
|
|
12
|
+
* The SQL is validated server-side to ensure it's a safe SELECT/WITH statement.
|
|
13
|
+
*/
|
|
14
|
+
@InputType()
|
|
15
|
+
class AdhocQueryInput {
|
|
16
|
+
@Field(() => String, { description: 'SQL query to execute. Must be a SELECT or WITH (CTE) statement.' })
|
|
17
|
+
SQL: string;
|
|
18
|
+
|
|
19
|
+
@Field(() => Int, { nullable: true, description: 'Query timeout in seconds. Defaults to 30.' })
|
|
20
|
+
TimeoutSeconds?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Resolver for executing ad-hoc (unsaved) SQL queries.
|
|
25
|
+
*
|
|
26
|
+
* Security:
|
|
27
|
+
* - SQL validated via SQLExpressionValidator (full_query context) — blocks mutations, dangerous operations
|
|
28
|
+
* - Executes on read-only connection pool only (no fallback to read-write)
|
|
29
|
+
* - Configurable timeout (default 30s)
|
|
30
|
+
* - Requires authenticated user (standard GraphQL auth, no @RequireSystemUser)
|
|
31
|
+
*
|
|
32
|
+
* Auto-discovered by MJServer's dynamic resolver import.
|
|
33
|
+
*/
|
|
34
|
+
@Resolver()
|
|
35
|
+
export class AdhocQueryResolver extends ResolverBase {
|
|
36
|
+
@Query(() => RunQueryResultType)
|
|
37
|
+
async ExecuteAdhocQuery(
|
|
38
|
+
@Arg('input', () => AdhocQueryInput) input: AdhocQueryInput,
|
|
39
|
+
@Ctx() context: AppContext
|
|
40
|
+
): Promise<RunQueryResultType> {
|
|
41
|
+
const startTime = Date.now();
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// 1. Security: validate SQL using SQLExpressionValidator
|
|
45
|
+
const validator = SQLExpressionValidator.Instance;
|
|
46
|
+
const validation = validator.validateFullQuery(input.SQL);
|
|
47
|
+
if (!validation.valid) {
|
|
48
|
+
return this.buildErrorResult(validation.error || 'SQL validation failed');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. Get READ-ONLY data source (no fallback to read-write)
|
|
52
|
+
let readOnlyDS: sql.ConnectionPool;
|
|
53
|
+
try {
|
|
54
|
+
readOnlyDS = GetReadOnlyDataSource(context.dataSources, { allowFallbackToReadWrite: false });
|
|
55
|
+
} catch {
|
|
56
|
+
return this.buildErrorResult('No read-only data source available for ad-hoc query execution');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 3. Execute with timeout
|
|
60
|
+
const timeoutMs = (input.TimeoutSeconds ?? 30) * 1000;
|
|
61
|
+
const request = new sql.Request(readOnlyDS);
|
|
62
|
+
|
|
63
|
+
const result = await Promise.race([
|
|
64
|
+
request.query(input.SQL),
|
|
65
|
+
new Promise<never>((_, reject) =>
|
|
66
|
+
setTimeout(() => reject(new Error('Query timeout exceeded')), timeoutMs)
|
|
67
|
+
)
|
|
68
|
+
]);
|
|
69
|
+
const executionTimeMs = Date.now() - startTime;
|
|
70
|
+
|
|
71
|
+
// 4. Return as RunQueryResultType
|
|
72
|
+
return {
|
|
73
|
+
QueryID: '',
|
|
74
|
+
QueryName: 'Ad-Hoc Query',
|
|
75
|
+
Success: true,
|
|
76
|
+
Results: JSON.stringify(result.recordset ?? []),
|
|
77
|
+
RowCount: result.recordset?.length ?? 0,
|
|
78
|
+
TotalRowCount: result.recordset?.length ?? 0,
|
|
79
|
+
ExecutionTime: executionTimeMs,
|
|
80
|
+
ErrorMessage: ''
|
|
81
|
+
};
|
|
82
|
+
} catch (err: unknown) {
|
|
83
|
+
const executionTimeMs = Date.now() - startTime;
|
|
84
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
85
|
+
|
|
86
|
+
// Handle timeout
|
|
87
|
+
if (errorMessage.includes('timeout') || errorMessage.includes('Timeout')) {
|
|
88
|
+
return {
|
|
89
|
+
QueryID: '',
|
|
90
|
+
QueryName: 'Ad-Hoc Query',
|
|
91
|
+
Success: false,
|
|
92
|
+
Results: '[]',
|
|
93
|
+
RowCount: 0,
|
|
94
|
+
TotalRowCount: 0,
|
|
95
|
+
ExecutionTime: executionTimeMs,
|
|
96
|
+
ErrorMessage: `Query execution exceeded ${input.TimeoutSeconds ?? 30} second timeout`
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
LogError(`Ad-hoc query execution failed: ${errorMessage}`);
|
|
101
|
+
return {
|
|
102
|
+
QueryID: '',
|
|
103
|
+
QueryName: 'Ad-Hoc Query',
|
|
104
|
+
Success: false,
|
|
105
|
+
Results: '[]',
|
|
106
|
+
RowCount: 0,
|
|
107
|
+
TotalRowCount: 0,
|
|
108
|
+
ExecutionTime: executionTimeMs,
|
|
109
|
+
ErrorMessage: `Query execution failed: ${errorMessage}`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private buildErrorResult(errorMessage: string): RunQueryResultType {
|
|
115
|
+
return {
|
|
116
|
+
QueryID: '',
|
|
117
|
+
QueryName: 'Ad-Hoc Query',
|
|
118
|
+
Success: false,
|
|
119
|
+
Results: '[]',
|
|
120
|
+
RowCount: 0,
|
|
121
|
+
TotalRowCount: 0,
|
|
122
|
+
ExecutionTime: 0,
|
|
123
|
+
ErrorMessage: errorMessage
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -6,7 +6,7 @@ import { MJQueryCategoryEntity, MJQueryPermissionEntity } from '@memberjunction/
|
|
|
6
6
|
import { MJQueryResolver } from '../generated/generated.js';
|
|
7
7
|
import { GetReadOnlyProvider, GetReadWriteProvider } from '../util.js';
|
|
8
8
|
import { DeleteOptionsInput } from '../generic/DeleteOptionsInput.js';
|
|
9
|
-
import {
|
|
9
|
+
import { MJQueryEntityServer } from '@memberjunction/core-entities-server';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Query status enumeration for GraphQL
|
|
@@ -425,8 +425,8 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
425
425
|
};
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
// Use
|
|
429
|
-
const record = await provider.GetEntityObject<
|
|
428
|
+
// Use MJQueryEntityServer which handles AI processing
|
|
429
|
+
const record = await provider.GetEntityObject<MJQueryEntityServer>("MJ: Queries", context.userPayload.userRecord);
|
|
430
430
|
|
|
431
431
|
// Set the fields from input, handling CategoryPath resolution
|
|
432
432
|
const fieldsToSet = {
|
|
@@ -638,9 +638,9 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
638
638
|
@PubSub() pubSub: PubSubEngine
|
|
639
639
|
): Promise<UpdateQueryResultType> {
|
|
640
640
|
try {
|
|
641
|
-
// Load the existing query using
|
|
641
|
+
// Load the existing query using MJQueryEntityServer
|
|
642
642
|
const provider = GetReadWriteProvider(context.providers);
|
|
643
|
-
const queryEntity = await provider.GetEntityObject<
|
|
643
|
+
const queryEntity = await provider.GetEntityObject<MJQueryEntityServer>('MJ: Queries', context.userPayload.userRecord);
|
|
644
644
|
if (!queryEntity || !await queryEntity.Load(input.ID)) {
|
|
645
645
|
return {
|
|
646
646
|
Success: false,
|
|
@@ -3,7 +3,7 @@ import { AppContext, UserPayload } from '../types.js';
|
|
|
3
3
|
import { DatabaseProviderBase, LogError, LogStatus, Metadata, RunView, UserInfo } from '@memberjunction/core';
|
|
4
4
|
import { MJConversationDetailEntity, MJConversationDetailAttachmentEntity } from '@memberjunction/core-entities';
|
|
5
5
|
import { AgentRunner } from '@memberjunction/ai-agents';
|
|
6
|
-
import {
|
|
6
|
+
import { MJAIAgentEntityExtended, MJAIAgentRunEntityExtended, ExecuteAgentResult, ConversationUtility, AttachmentData } from '@memberjunction/ai-core-plus';
|
|
7
7
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
8
8
|
import { ChatMessage } from '@memberjunction/ai';
|
|
9
9
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
@@ -207,12 +207,12 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
207
207
|
/**
|
|
208
208
|
* Validate the agent entity
|
|
209
209
|
*/
|
|
210
|
-
private async validateAgent(agentId: string, currentUser: any): Promise<
|
|
210
|
+
private async validateAgent(agentId: string, currentUser: any): Promise<MJAIAgentEntityExtended> {
|
|
211
211
|
// Use AIEngine to get cached agent data
|
|
212
212
|
await AIEngine.Instance.Config(false, currentUser);
|
|
213
213
|
|
|
214
214
|
// Find agent in cached collection
|
|
215
|
-
const agentEntity = AIEngine.Instance.Agents.find((a:
|
|
215
|
+
const agentEntity = AIEngine.Instance.Agents.find((a: MJAIAgentEntityExtended) => a.ID === agentId);
|
|
216
216
|
|
|
217
217
|
if (!agentEntity) {
|
|
218
218
|
throw new Error(`AI Agent with ID ${agentId} not found`);
|
|
@@ -630,7 +630,7 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
630
630
|
* Notification includes navigation link back to the conversation
|
|
631
631
|
*/
|
|
632
632
|
private async createCompletionNotification(
|
|
633
|
-
agentRun:
|
|
633
|
+
agentRun: MJAIAgentRunEntityExtended,
|
|
634
634
|
artifactInfo: { artifactId: string; versionId: string; versionNumber: number },
|
|
635
635
|
conversationDetailId: string,
|
|
636
636
|
contextUser: UserInfo,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Resolver, Mutation, Query, Arg, Ctx, ObjectType, Field, Int } from 'type-graphql';
|
|
2
2
|
import { AppContext, UserPayload } from '../types.js';
|
|
3
3
|
import { DatabaseProviderBase, LogError, LogStatus, Metadata } from '@memberjunction/core';
|
|
4
|
-
import {
|
|
4
|
+
import { MJAIPromptEntityExtended, MJAIModelEntityExtended } from '@memberjunction/ai-core-plus';
|
|
5
5
|
import { AIPromptRunner } from '@memberjunction/ai-prompts';
|
|
6
6
|
import { AIPromptParams } from '@memberjunction/ai-core-plus';
|
|
7
7
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
@@ -156,7 +156,7 @@ export class RunAIPromptResolver extends ResolverBase {
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// Load the AI prompt entity
|
|
159
|
-
const promptEntity = await p.GetEntityObject<
|
|
159
|
+
const promptEntity = await p.GetEntityObject<MJAIPromptEntityExtended>('MJ: AI Prompts', currentUser);
|
|
160
160
|
await promptEntity.Load(promptId);
|
|
161
161
|
|
|
162
162
|
if (!promptEntity.IsSaved) {
|
|
@@ -402,7 +402,7 @@ export class RunAIPromptResolver extends ResolverBase {
|
|
|
402
402
|
preferredModels: string[] | undefined,
|
|
403
403
|
modelPower: string,
|
|
404
404
|
contextUser: any
|
|
405
|
-
): Promise<
|
|
405
|
+
): Promise<MJAIModelEntityExtended> {
|
|
406
406
|
// Ensure AI Engine is configured
|
|
407
407
|
await AIEngine.Instance.Config(false, contextUser);
|
|
408
408
|
|
|
@@ -413,7 +413,7 @@ export class RunAIPromptResolver extends ResolverBase {
|
|
|
413
413
|
);
|
|
414
414
|
|
|
415
415
|
// Filter to only models with valid API keys
|
|
416
|
-
const modelsWithKeys:
|
|
416
|
+
const modelsWithKeys: MJAIModelEntityExtended[] = [];
|
|
417
417
|
for (const model of allModels) {
|
|
418
418
|
const apiKey = GetAIAPIKey(model.DriverClass);
|
|
419
419
|
if (apiKey && apiKey.trim().length > 0) {
|
|
@@ -443,7 +443,7 @@ export class RunAIPromptResolver extends ResolverBase {
|
|
|
443
443
|
// Sort by PowerRank for power-based selection
|
|
444
444
|
modelsWithKeys.sort((a, b) => (b.PowerRank || 0) - (a.PowerRank || 0));
|
|
445
445
|
|
|
446
|
-
let selectedModel:
|
|
446
|
+
let selectedModel: MJAIModelEntityExtended;
|
|
447
447
|
switch (modelPower) {
|
|
448
448
|
case 'lowest':
|
|
449
449
|
selectedModel = modelsWithKeys[modelsWithKeys.length - 1];
|
|
@@ -466,7 +466,7 @@ export class RunAIPromptResolver extends ResolverBase {
|
|
|
466
466
|
* Helper method to select an embedding model by size
|
|
467
467
|
* @private
|
|
468
468
|
*/
|
|
469
|
-
private selectEmbeddingModelBySize(modelSize: string):
|
|
469
|
+
private selectEmbeddingModelBySize(modelSize: string): MJAIModelEntityExtended {
|
|
470
470
|
const localModels = AIEngine.Instance.LocalEmbeddingModels;
|
|
471
471
|
|
|
472
472
|
if (!localModels || localModels.length === 0) {
|
|
@@ -541,7 +541,7 @@ export class RunAIPromptResolver extends ResolverBase {
|
|
|
541
541
|
* Helper method to format simple prompt result
|
|
542
542
|
* @private
|
|
543
543
|
*/
|
|
544
|
-
private formatSimpleResult(chatResult: any, model:
|
|
544
|
+
private formatSimpleResult(chatResult: any, model: MJAIModelEntityExtended, executionTime: number): SimplePromptResult {
|
|
545
545
|
if (!chatResult || !chatResult.success) {
|
|
546
546
|
return {
|
|
547
547
|
success: false,
|
|
@@ -1,7 +1,7 @@
|
|
|
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 { MJTemplateContentEntity,
|
|
4
|
+
import { MJTemplateContentEntity, MJTemplateEntityExtended } from '@memberjunction/core-entities';
|
|
5
5
|
import { TemplateEngineServer } from '@memberjunction/templates';
|
|
6
6
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
7
7
|
import { GetReadWriteProvider } from '../util.js';
|
|
@@ -63,7 +63,7 @@ export class RunTemplateResolver extends ResolverBase {
|
|
|
63
63
|
|
|
64
64
|
const p = GetReadWriteProvider(providers);
|
|
65
65
|
// Load the template entity
|
|
66
|
-
const templateEntity = await p.GetEntityObject<
|
|
66
|
+
const templateEntity = await p.GetEntityObject<MJTemplateEntityExtended>('MJ: Templates', currentUser);
|
|
67
67
|
await templateEntity.Load(templateId);
|
|
68
68
|
|
|
69
69
|
if (!templateEntity.IsSaved) {
|
|
@@ -3,7 +3,7 @@ import { EntitySaveOptions, Metadata } from '@memberjunction/core';
|
|
|
3
3
|
import { AppContext, Arg, Ctx, Int, Query, Resolver, UserPayload } from '@memberjunction/server';
|
|
4
4
|
import { MJUserView_, MJUserViewResolverBase } from '../generated/generated.js';
|
|
5
5
|
import { UserResolver } from './UserResolver.js';
|
|
6
|
-
import { MJUserViewEntity,
|
|
6
|
+
import { MJUserViewEntity, MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
7
7
|
import { GetReadOnlyProvider } from '../util.js';
|
|
8
8
|
|
|
9
9
|
@Resolver(MJUserView_)
|
|
@@ -54,7 +54,7 @@ export class UserViewResolver extends MJUserViewResolverBase {
|
|
|
54
54
|
// filter state which in turn will be used to update the where clause in the entity sub-class.
|
|
55
55
|
const p = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
|
|
56
56
|
const u = this.GetUserFromPayload(userPayload);
|
|
57
|
-
const viewEntity = <
|
|
57
|
+
const viewEntity = <MJUserViewEntityExtended>await p.GetEntityObject('MJ: User Views', u);
|
|
58
58
|
await viewEntity.Load(ID);
|
|
59
59
|
viewEntity.UpdateWhereClause();
|
|
60
60
|
|
|
@@ -5,7 +5,7 @@ import { ChatMessageRole } from '@memberjunction/ai';
|
|
|
5
5
|
import { PubSubEngine } from 'type-graphql';
|
|
6
6
|
import { UserPayload } from '../types.js';
|
|
7
7
|
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
|
|
8
|
-
import {
|
|
8
|
+
import { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Task definition from LLM response
|
|
@@ -268,9 +268,9 @@ export class TaskOrchestrator {
|
|
|
268
268
|
/**
|
|
269
269
|
* Find agent by name
|
|
270
270
|
*/
|
|
271
|
-
private async findAgentByName(agentName: string): Promise<
|
|
271
|
+
private async findAgentByName(agentName: string): Promise<MJAIAgentEntityExtended | null> {
|
|
272
272
|
const rv = new RunView();
|
|
273
|
-
const result = await rv.RunView<
|
|
273
|
+
const result = await rv.RunView<MJAIAgentEntityExtended>({
|
|
274
274
|
EntityName: 'MJ: AI Agents',
|
|
275
275
|
ExtraFilter: `Name='${agentName.replace(/'/g, "''")}'`,
|
|
276
276
|
ResultType: 'entity_object'
|
|
@@ -475,7 +475,7 @@ export class TaskOrchestrator {
|
|
|
475
475
|
|
|
476
476
|
// Load the agent entity
|
|
477
477
|
const md = new Metadata();
|
|
478
|
-
const agentEntity = await md.GetEntityObject<
|
|
478
|
+
const agentEntity = await md.GetEntityObject<MJAIAgentEntityExtended>('MJ: AI Agents', this.contextUser);
|
|
479
479
|
const loaded = await agentEntity.Load(task.AgentID!);
|
|
480
480
|
if (!loaded) {
|
|
481
481
|
throw new Error(`Agent with ID ${task.AgentID} not found`);
|
|
@@ -695,7 +695,7 @@ export class TaskOrchestrator {
|
|
|
695
695
|
private async createArtifactFromOutput(
|
|
696
696
|
output: { type: 'message' | 'payload', content: any },
|
|
697
697
|
conversationDetailId: string,
|
|
698
|
-
agent:
|
|
698
|
+
agent: MJAIAgentEntityExtended,
|
|
699
699
|
taskName: string
|
|
700
700
|
): Promise<void> {
|
|
701
701
|
try {
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AggregateExpression, DatabaseProviderBase, UserInfo } from '@memberjunction/core';
|
|
2
|
-
import {
|
|
2
|
+
import { MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
3
3
|
import { GraphQLSchema } from 'graphql';
|
|
4
4
|
import sql from 'mssql';
|
|
5
5
|
import { getSystemUser } from './auth/index.js';
|
|
@@ -68,7 +68,7 @@ export type DirectiveBuilder = {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
export type RunViewGenericParams = {
|
|
71
|
-
viewInfo:
|
|
71
|
+
viewInfo: MJUserViewEntityExtended;
|
|
72
72
|
provider: DatabaseProviderBase;
|
|
73
73
|
extraFilter: string;
|
|
74
74
|
orderBy: string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionPlugin.d.ts","sourceRoot":"","sources":["../../src/apolloServer/TransactionPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAgF,MAAM,gBAAgB,CAAC;AAElI,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,CAAC,UAAU,CAgD5D,CAAC"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import sql from 'mssql';
|
|
2
|
-
export const TransactionPlugin = {
|
|
3
|
-
async requestDidStart(requestContext) {
|
|
4
|
-
const start = Date.now();
|
|
5
|
-
const query = requestContext.request.query || '';
|
|
6
|
-
const isMutation = /^\s*mutation\b/i.test(query);
|
|
7
|
-
if (!isMutation) {
|
|
8
|
-
return null;
|
|
9
|
-
}
|
|
10
|
-
const pool = requestContext.contextValue.dataSource;
|
|
11
|
-
const transaction = new sql.Transaction(pool);
|
|
12
|
-
requestContext.contextValue.transaction = transaction;
|
|
13
|
-
console.log('Starting transaction wrapper, time spent: ', Date.now() - start, 'ms ');
|
|
14
|
-
await transaction.begin();
|
|
15
|
-
return {
|
|
16
|
-
didEncounterErrors: async (requestContext) => {
|
|
17
|
-
console.log('Error in transaction wrapper: ' + requestContext.errors, 'time spent: ', Date.now() - start, 'ms');
|
|
18
|
-
},
|
|
19
|
-
executionDidStart: async () => {
|
|
20
|
-
return {
|
|
21
|
-
executionDidEnd: async (err) => {
|
|
22
|
-
try {
|
|
23
|
-
if (err) {
|
|
24
|
-
console.log('Error in transaction, rolling back, time spent: ', Date.now() - start, 'ms ');
|
|
25
|
-
console.error('Rolling back transaction', err);
|
|
26
|
-
await transaction.rollback();
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
console.log('Committing transaction, time spent: ', Date.now() - start, 'ms ');
|
|
30
|
-
await transaction.commit();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
catch (execErr) {
|
|
34
|
-
console.log('Execution Error, time spent: ', Date.now() - start, 'ms ');
|
|
35
|
-
console.error(execErr);
|
|
36
|
-
}
|
|
37
|
-
finally {
|
|
38
|
-
console.log('Transaction complete, time spent: ', Date.now() - start, 'ms ');
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
//# sourceMappingURL=TransactionPlugin.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionPlugin.js","sourceRoot":"","sources":["../../src/apolloServer/TransactionPlugin.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,OAAO,CAAC;AAGxB,MAAM,CAAC,MAAM,iBAAiB,GAAmC;IAC/D,KAAK,CAAC,eAAe,CAAC,cAAc;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEjD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QAKD,MAAM,IAAI,GAAuB,cAAc,CAAC,YAAY,CAAC,UAAU,CAAC;QACxE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAG7C,cAAc,CAAC,YAAoB,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;QACrF,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;QAE1B,OAAO;YACL,kBAAkB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;gBAC3C,OAAO,CAAC,GAAG,CAAC,gCAAgC,GAAG,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC;YAClH,CAAC;YACD,iBAAiB,EAAE,KAAK,IAAI,EAAE;gBAC5B,OAAO;oBACL,eAAe,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;wBAC7B,IAAI,CAAC;4BACH,IAAI,GAAG,EAAE,CAAC;gCACR,OAAO,CAAC,GAAG,CAAC,kDAAkD,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;gCAC3F,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;gCAC/C,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC;4BAC/B,CAAC;iCAAM,CAAC;gCACN,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;gCAC/E,MAAM,WAAW,CAAC,MAAM,EAAE,CAAC;4BAC7B,CAAC;wBACH,CAAC;wBAAC,OAAO,OAAO,EAAE,CAAC;4BACjB,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;4BACxE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBACzB,CAAC;gCAAS,CAAC;4BACT,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;wBAC/E,CAAC;oBACH,CAAC;iBACF,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"backward-compatibility.test.d.ts","sourceRoot":"","sources":["../../../src/auth/__tests__/backward-compatibility.test.ts"],"names":[],"mappings":""}
|