@memberjunction/server 2.14.0 → 2.16.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/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -1
- package/dist/config.js.map +1 -1
- package/dist/generated/generated.d.ts +41 -0
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +267 -0
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +4 -0
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +35 -9
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +5 -4
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +68 -10
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/InfoResolver.d.ts +9 -0
- package/dist/resolvers/InfoResolver.d.ts.map +1 -0
- package/dist/resolvers/InfoResolver.js +41 -0
- package/dist/resolvers/InfoResolver.js.map +1 -0
- package/package.json +24 -23
- package/src/config.ts +6 -1
- package/src/generated/generated.ts +167 -1
- package/src/generic/ResolverBase.ts +70 -33
- package/src/resolvers/AskSkipResolver.ts +85 -12
- package/src/resolvers/InfoResolver.ts +19 -0
|
@@ -1,18 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BaseEntity,
|
|
3
|
+
BaseEntityEvent,
|
|
4
|
+
CompositeKey,
|
|
5
|
+
EntityFieldTSType,
|
|
6
|
+
EntityPermissionType,
|
|
7
|
+
LogError,
|
|
8
|
+
Metadata,
|
|
9
|
+
RunView,
|
|
10
|
+
RunViewParams,
|
|
11
|
+
RunViewResult,
|
|
12
|
+
UserInfo,
|
|
13
|
+
} from '@memberjunction/core';
|
|
2
14
|
import { AuditLogEntity, UserViewEntity } from '@memberjunction/core-entities';
|
|
3
15
|
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
4
16
|
import { PubSubEngine } from 'type-graphql';
|
|
5
17
|
import { GraphQLError } from 'graphql';
|
|
6
18
|
import { DataSource } from 'typeorm';
|
|
19
|
+
import { httpTransport, CloudEvent, emitterFor } from 'cloudevents';
|
|
7
20
|
|
|
8
21
|
import { RunViewGenericParams, UserPayload } from '../types.js';
|
|
9
22
|
import { RunDynamicViewInput, RunViewByIDInput, RunViewByNameInput } from './RunViewResolver.js';
|
|
10
23
|
import { DeleteOptionsInput } from './DeleteOptionsInput.js';
|
|
11
|
-
import { MJGlobal } from '@memberjunction/global';
|
|
24
|
+
import { MJEvent, MJEventType, MJGlobal } from '@memberjunction/global';
|
|
12
25
|
import { PUSH_STATUS_UPDATES_TOPIC } from './PushStatusResolver.js';
|
|
13
26
|
import { FieldMapper } from '@memberjunction/graphql-dataprovider';
|
|
14
27
|
|
|
15
28
|
export class ResolverBase {
|
|
29
|
+
private _emit = process.env.CLOUDEVENTS_HTTP_TRANSPORT ? emitterFor(httpTransport(process.env.CLOUDEVENTS_HTTP_TRANSPORT)) : null;
|
|
30
|
+
private _cloudeventsHeaders = process.env.CLOUDEVENTS_HTTP_HEADERS ? JSON.parse(process.env.CLOUDEVENTS_HTTP_HEADERS) : {};
|
|
31
|
+
|
|
16
32
|
protected MapFieldNamesToCodeNames(entityName: string, dataObject: any) {
|
|
17
33
|
// for the given entity name provided, check to see if there are any fields
|
|
18
34
|
// where the code name is different from the field name, and for just those
|
|
@@ -28,7 +44,7 @@ export class ResolverBase {
|
|
|
28
44
|
entityInfo.Fields.forEach((f) => {
|
|
29
45
|
if (dataObject.hasOwnProperty(f.Name)) {
|
|
30
46
|
// GraphQL doesn't allow us to pass back fields with __ so we are mapping our special field cases that start with __mj_ to _mj__ for transport - they are converted back on the other side automatically
|
|
31
|
-
const mappedFieldName = mapper.MapFieldName(f.CodeName)
|
|
47
|
+
const mappedFieldName = mapper.MapFieldName(f.CodeName);
|
|
32
48
|
if (mappedFieldName !== f.Name) {
|
|
33
49
|
dataObject[mappedFieldName] = dataObject[f.Name];
|
|
34
50
|
delete dataObject[f.Name];
|
|
@@ -134,7 +150,7 @@ export class ResolverBase {
|
|
|
134
150
|
if (!entity) throw new Error(`Entity ${viewInput.EntityName} not found in metadata`);
|
|
135
151
|
|
|
136
152
|
const viewInfo: UserViewEntity = {
|
|
137
|
-
ID:
|
|
153
|
+
ID: '',
|
|
138
154
|
Entity: viewInput.EntityName,
|
|
139
155
|
EntityID: entity.ID,
|
|
140
156
|
EntityBaseView: entity.BaseView as string,
|
|
@@ -164,22 +180,23 @@ export class ResolverBase {
|
|
|
164
180
|
}
|
|
165
181
|
}
|
|
166
182
|
|
|
167
|
-
async RunViewsGeneric(
|
|
183
|
+
async RunViewsGeneric(
|
|
184
|
+
viewInputs: (RunViewByNameInput & RunViewByIDInput & RunDynamicViewInput)[],
|
|
185
|
+
dataSource: DataSource,
|
|
186
|
+
userPayload: UserPayload,
|
|
187
|
+
pubSub: PubSubEngine
|
|
188
|
+
) {
|
|
168
189
|
let md: Metadata | null = null;
|
|
169
190
|
let params: RunViewGenericParams[] = [];
|
|
170
|
-
for(const viewInput of viewInputs) {
|
|
191
|
+
for (const viewInput of viewInputs) {
|
|
171
192
|
try {
|
|
172
193
|
let viewInfo: UserViewEntity | null = null;
|
|
173
194
|
|
|
174
|
-
if(viewInput.ViewName) {
|
|
175
|
-
viewInfo = this.safeFirstArrayElement(
|
|
176
|
-
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
else if(viewInput.ViewID) {
|
|
195
|
+
if (viewInput.ViewName) {
|
|
196
|
+
viewInfo = this.safeFirstArrayElement(await this.findBy(dataSource, 'User Views', { Name: viewInput.ViewName }));
|
|
197
|
+
} else if (viewInput.ViewID) {
|
|
180
198
|
viewInfo = this.safeFirstArrayElement(await this.findBy(dataSource, 'User Views', { ID: viewInput.ViewID }));
|
|
181
|
-
}
|
|
182
|
-
else if(viewInput.EntityName) {
|
|
199
|
+
} else if (viewInput.EntityName) {
|
|
183
200
|
md = md || new Metadata();
|
|
184
201
|
const entity = md.Entities.find((e) => e.Name === viewInput.EntityName);
|
|
185
202
|
if (!entity) {
|
|
@@ -188,14 +205,13 @@ export class ResolverBase {
|
|
|
188
205
|
|
|
189
206
|
// only providing a few bits of data here, but it's enough to get the view to run
|
|
190
207
|
viewInfo = {
|
|
191
|
-
ID:
|
|
208
|
+
ID: '',
|
|
192
209
|
Entity: viewInput.EntityName,
|
|
193
210
|
EntityID: entity.ID,
|
|
194
211
|
EntityBaseView: entity.BaseView,
|
|
195
212
|
} as UserViewEntity;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
throw new Error("Unable to determine input type");
|
|
213
|
+
} else {
|
|
214
|
+
throw new Error('Unable to determine input type');
|
|
199
215
|
}
|
|
200
216
|
|
|
201
217
|
params.push({
|
|
@@ -214,9 +230,8 @@ export class ResolverBase {
|
|
|
214
230
|
auditLogDescription: viewInput.AuditLogDescription,
|
|
215
231
|
resultType: viewInput.ResultType,
|
|
216
232
|
userPayload,
|
|
217
|
-
pubSub
|
|
233
|
+
pubSub,
|
|
218
234
|
});
|
|
219
|
-
|
|
220
235
|
} catch (err) {
|
|
221
236
|
LogError(err);
|
|
222
237
|
return null;
|
|
@@ -227,7 +242,26 @@ export class ResolverBase {
|
|
|
227
242
|
return results;
|
|
228
243
|
}
|
|
229
244
|
|
|
245
|
+
protected async EmitCloudEvent({ component, event, eventCode, args }: MJEvent) {
|
|
246
|
+
if (this._emit && event === MJEventType.ComponentEvent && eventCode === BaseEntity.BaseEventCode) {
|
|
247
|
+
const extendedType = args instanceof BaseEntityEvent ? `.${args.type}` : '';
|
|
248
|
+
const type = `MemberJunction.${event}${extendedType}`;
|
|
249
|
+
const source = `${process.env.CLOUDEVENTS_SOURCE ?? 'MemberJunction'}`;
|
|
250
|
+
const [subject, rawData] = args instanceof BaseEntityEvent ? [args.baseEntity.EntityInfo.CodeName, args.payload] : [undefined, args];
|
|
251
|
+
const data = (typeof rawData === 'object' ? rawData : { payload: rawData }) ?? {};
|
|
252
|
+
const cloudEvent = new CloudEvent({ source, subject, type, data });
|
|
230
253
|
|
|
254
|
+
try {
|
|
255
|
+
const cloudeventTransportResponse = await this._emit(cloudEvent, { headers: this._cloudeventsHeaders });
|
|
256
|
+
const cloudeventResponse = JSON.stringify(cloudeventTransportResponse);
|
|
257
|
+
if (/error/i.test(cloudeventResponse)) {
|
|
258
|
+
console.error('CloudEvent ERROR', cloudeventResponse);
|
|
259
|
+
}
|
|
260
|
+
} catch (e) {
|
|
261
|
+
console.error('CloudEvent ERROR', JSON.stringify(e));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
231
265
|
|
|
232
266
|
protected CheckUserReadPermissions(entityName: string, userPayload: UserPayload | null) {
|
|
233
267
|
const md = new Metadata();
|
|
@@ -326,10 +360,12 @@ export class ResolverBase {
|
|
|
326
360
|
const rv = new RunView();
|
|
327
361
|
let RunViewParams: RunViewParams[] = [];
|
|
328
362
|
let contextUser: UserInfo | null = null;
|
|
329
|
-
for(const param of params){
|
|
363
|
+
for (const param of params) {
|
|
330
364
|
if (param.viewInfo && param.userPayload) {
|
|
331
365
|
md = md || new Metadata();
|
|
332
|
-
const user: UserInfo = UserCache.Users.find(
|
|
366
|
+
const user: UserInfo = UserCache.Users.find(
|
|
367
|
+
(u) => u.Email.toLowerCase().trim() === param.userPayload?.email.toLowerCase().trim()
|
|
368
|
+
);
|
|
333
369
|
if (!user) {
|
|
334
370
|
throw new Error(`User ${param.userPayload?.email} not found in metadata`);
|
|
335
371
|
}
|
|
@@ -337,7 +373,7 @@ export class ResolverBase {
|
|
|
337
373
|
contextUser = contextUser || user;
|
|
338
374
|
|
|
339
375
|
const entityInfo = md.Entities.find((e) => e.Name === param.viewInfo.Entity);
|
|
340
|
-
if (!entityInfo){
|
|
376
|
+
if (!entityInfo) {
|
|
341
377
|
throw new Error(`Entity ${param.viewInfo.Entity} not found in metadata`);
|
|
342
378
|
}
|
|
343
379
|
}
|
|
@@ -381,7 +417,7 @@ export class ResolverBase {
|
|
|
381
417
|
|
|
382
418
|
// go through the result and convert all fields that start with __mj_*** to _mj__*** for GraphQL transport
|
|
383
419
|
const mapper = new FieldMapper();
|
|
384
|
-
for(const runViewResult of runViewResults){
|
|
420
|
+
for (const runViewResult of runViewResults) {
|
|
385
421
|
if (runViewResult && runViewResult.Success) {
|
|
386
422
|
for (const result of runViewResult.Results) {
|
|
387
423
|
mapper.MapFields(result);
|
|
@@ -390,8 +426,7 @@ export class ResolverBase {
|
|
|
390
426
|
}
|
|
391
427
|
|
|
392
428
|
return runViewResults;
|
|
393
|
-
}
|
|
394
|
-
catch (err) {
|
|
429
|
+
} catch (err) {
|
|
395
430
|
console.log(err);
|
|
396
431
|
throw err;
|
|
397
432
|
}
|
|
@@ -453,8 +488,9 @@ export class ResolverBase {
|
|
|
453
488
|
auditLog.UserID = userInfo.ID;
|
|
454
489
|
auditLog.AuditLogTypeID = auditLogType.ID;
|
|
455
490
|
|
|
456
|
-
if (authorization)
|
|
491
|
+
if (authorization) {
|
|
457
492
|
auditLog.AuthorizationID = authorization.ID;
|
|
493
|
+
}
|
|
458
494
|
|
|
459
495
|
if (status?.trim().toLowerCase() === 'success') auditLog.Status = 'Success';
|
|
460
496
|
else auditLog.Status = 'Failed';
|
|
@@ -501,8 +537,10 @@ export class ResolverBase {
|
|
|
501
537
|
|
|
502
538
|
protected ListenForEntityMessages(entityObject: BaseEntity, pubSub: PubSubEngine, userPayload: UserPayload) {
|
|
503
539
|
// listen for events from the entityObject in case it is a long running task and we can push messages back to the client via pubSub
|
|
504
|
-
MJGlobal.Instance.GetEventListener(false).subscribe((event) => {
|
|
540
|
+
MJGlobal.Instance.GetEventListener(false).subscribe(async (event) => {
|
|
505
541
|
if (event) {
|
|
542
|
+
await this.EmitCloudEvent(event);
|
|
543
|
+
|
|
506
544
|
if (event.component === entityObject && event.args && event.args.message) {
|
|
507
545
|
// message from our entity object, relay it to the client
|
|
508
546
|
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
@@ -554,8 +592,9 @@ export class ResolverBase {
|
|
|
554
592
|
const entityInfo = entityObject.EntityInfo;
|
|
555
593
|
const clientNewValues = {};
|
|
556
594
|
Object.keys(input).forEach((key) => {
|
|
557
|
-
if (key !== 'OldValues___')
|
|
595
|
+
if (key !== 'OldValues___') {
|
|
558
596
|
clientNewValues[key] = input[key];
|
|
597
|
+
}
|
|
559
598
|
}); // grab all the props except for the OldValues property
|
|
560
599
|
|
|
561
600
|
if (entityInfo.TrackRecordChanges || !input.OldValues___) {
|
|
@@ -574,8 +613,7 @@ export class ResolverBase {
|
|
|
574
613
|
if (input.OldValues___) {
|
|
575
614
|
// we DO have OldValues, so we need to do a more in depth analysis
|
|
576
615
|
this.TestAndSetClientOldValuesToDBValues(input, clientNewValues, entityObject);
|
|
577
|
-
}
|
|
578
|
-
else {
|
|
616
|
+
} else {
|
|
579
617
|
// no OldValues, so we can just set the new values from input
|
|
580
618
|
entityObject.SetMany(input);
|
|
581
619
|
}
|
|
@@ -585,8 +623,7 @@ export class ResolverBase {
|
|
|
585
623
|
extensions: { code: 'LOAD_ENTITY_ERROR', entityName },
|
|
586
624
|
});
|
|
587
625
|
}
|
|
588
|
-
}
|
|
589
|
-
else {
|
|
626
|
+
} else {
|
|
590
627
|
// we get here if we are NOT tracking changes and we DO have OldValues, so we can load from them
|
|
591
628
|
const oldValues = {};
|
|
592
629
|
// for each item in the oldValues array, add it to the oldValues object
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
SkipAPIRunScriptRequest,
|
|
19
19
|
SkipAPIRequestAPIKey,
|
|
20
20
|
SkipRequestPhase,
|
|
21
|
+
SkipAPIAgentNote,
|
|
21
22
|
} from '@memberjunction/skip-types';
|
|
22
23
|
|
|
23
24
|
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
|
|
@@ -75,7 +76,7 @@ export class AskSkipResultType {
|
|
|
75
76
|
@Resolver(AskSkipResultType)
|
|
76
77
|
export class AskSkipResolver {
|
|
77
78
|
private static _defaultNewChatName = 'New Chat';
|
|
78
|
-
private static _maxHistoricalMessages =
|
|
79
|
+
private static _maxHistoricalMessages = 30;
|
|
79
80
|
|
|
80
81
|
/**
|
|
81
82
|
* Handles a simple chat request from a user to Skip, using a particular data record
|
|
@@ -146,7 +147,7 @@ export class AskSkipResolver {
|
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
const input = this.buildSkipAPIRequest(messages, ConversationId, dataContext, 'chat_with_a_record', false, false);
|
|
150
|
+
const input = await this.buildSkipAPIRequest(messages, ConversationId, dataContext, 'chat_with_a_record', false, false, false, user);
|
|
150
151
|
messages.push({
|
|
151
152
|
content: UserQuestion,
|
|
152
153
|
role: 'user',
|
|
@@ -219,16 +220,19 @@ export class AskSkipResolver {
|
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
222
|
|
|
222
|
-
protected buildSkipAPIRequest(
|
|
223
|
+
protected async buildSkipAPIRequest(
|
|
223
224
|
messages: SkipMessage[],
|
|
224
225
|
conversationId: string,
|
|
225
226
|
dataContext: DataContext,
|
|
226
227
|
requestPhase: SkipRequestPhase,
|
|
227
228
|
includeEntities: boolean,
|
|
228
|
-
includeQueries: boolean
|
|
229
|
-
|
|
229
|
+
includeQueries: boolean,
|
|
230
|
+
includeNotes: boolean,
|
|
231
|
+
contextUser: UserInfo
|
|
232
|
+
): Promise<SkipAPIRequest> {
|
|
230
233
|
const entities = includeEntities ? this.BuildSkipEntities() : [];
|
|
231
234
|
const queries = includeQueries ? this.BuildSkipQueries() : [];
|
|
235
|
+
const notes = includeNotes ? await this.BuildSkipAgentNotes(contextUser) : [];
|
|
232
236
|
const input: SkipAPIRequest = {
|
|
233
237
|
apiKeys: this.buildSkipAPIKeys(),
|
|
234
238
|
organizationInfo: configInfo?.askSkip?.organizationInfo,
|
|
@@ -239,6 +243,7 @@ export class AskSkipResolver {
|
|
|
239
243
|
requestPhase: requestPhase,
|
|
240
244
|
entities: entities,
|
|
241
245
|
queries: queries,
|
|
246
|
+
notes: notes
|
|
242
247
|
};
|
|
243
248
|
return input;
|
|
244
249
|
}
|
|
@@ -260,7 +265,7 @@ export class AskSkipResolver {
|
|
|
260
265
|
if (!user) throw new Error(`User ${userPayload.email} not found in UserCache`);
|
|
261
266
|
const dataContext: DataContext = new DataContext();
|
|
262
267
|
await dataContext.Load(DataContextId, dataSource, true, false, 0, user);
|
|
263
|
-
const input = this.buildSkipAPIRequest([], '', dataContext, 'run_existing_script', false, false);
|
|
268
|
+
const input = await this.buildSkipAPIRequest([], '', dataContext, 'run_existing_script', false, false, false, user);
|
|
264
269
|
return this.handleSimpleSkipPostRequest(input);
|
|
265
270
|
}
|
|
266
271
|
|
|
@@ -318,7 +323,8 @@ export class AskSkipResolver {
|
|
|
318
323
|
AskSkipResolver._maxHistoricalMessages
|
|
319
324
|
);
|
|
320
325
|
|
|
321
|
-
const
|
|
326
|
+
const conversationDetailCount = 1
|
|
327
|
+
const input = await this.buildSkipAPIRequest(messages, ConversationId, dataContext, 'initial_request', true, true, true, user);
|
|
322
328
|
|
|
323
329
|
return this.HandleSkipRequest(
|
|
324
330
|
input,
|
|
@@ -332,7 +338,8 @@ export class AskSkipResolver {
|
|
|
332
338
|
convoEntity,
|
|
333
339
|
convoDetailEntity,
|
|
334
340
|
dataContext,
|
|
335
|
-
dataContextEntity
|
|
341
|
+
dataContextEntity,
|
|
342
|
+
conversationDetailCount,
|
|
336
343
|
);
|
|
337
344
|
}
|
|
338
345
|
|
|
@@ -376,6 +383,44 @@ export class AskSkipResolver {
|
|
|
376
383
|
});
|
|
377
384
|
}
|
|
378
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Builds up the array of notes that are applicable for Skip to receive from MJAPI
|
|
388
|
+
*/
|
|
389
|
+
protected async BuildSkipAgentNotes(contextUser: UserInfo): Promise<SkipAPIAgentNote[]> {
|
|
390
|
+
try {
|
|
391
|
+
const md = new Metadata();
|
|
392
|
+
if (md.EntityByName('AI Agent Notes')) {
|
|
393
|
+
const rv = new RunView();
|
|
394
|
+
const result = await rv.RunView({
|
|
395
|
+
EntityName: "AI Agent Notes",
|
|
396
|
+
ExtraFilter: "Agent='Skip'"
|
|
397
|
+
}, contextUser)
|
|
398
|
+
if (result && result.Success) {
|
|
399
|
+
return result.Results.map((r) => {
|
|
400
|
+
return {
|
|
401
|
+
id: r.ID,
|
|
402
|
+
typeId: r.TypeID,
|
|
403
|
+
type: r.Type,
|
|
404
|
+
note: r.Note,
|
|
405
|
+
createdAt: r.__mj_CreatedAt,
|
|
406
|
+
updatedAt: r.__mj_UpdatedAt,
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
else
|
|
411
|
+
return [];
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
console.warn(`No AI Agent Notes entity found in the metadata, so no notes will be sent to Skip`);
|
|
415
|
+
return []; // no agent notes configured in this MJ system, so not an error, just return empty array
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
catch (e) {
|
|
419
|
+
LogError(e);
|
|
420
|
+
return []; // non- fatal error just return an empty array
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
379
424
|
protected BuildSkipEntities(): SkipEntityInfo[] {
|
|
380
425
|
// build the entity info for skip in its format which is
|
|
381
426
|
// narrower in scope than our native MJ metadata
|
|
@@ -677,10 +722,34 @@ export class AskSkipResolver {
|
|
|
677
722
|
convoEntity: ConversationEntity,
|
|
678
723
|
convoDetailEntity: ConversationDetailEntity,
|
|
679
724
|
dataContext: DataContext,
|
|
680
|
-
dataContextEntity: DataContextEntity
|
|
725
|
+
dataContextEntity: DataContextEntity,
|
|
726
|
+
conversationDetailCount: number
|
|
681
727
|
): Promise<AskSkipResultType> {
|
|
682
728
|
LogStatus(` >>> HandleSkipRequest: Sending request to Skip API: ${___skipAPIurl}`);
|
|
683
729
|
|
|
730
|
+
if (conversationDetailCount > 10) {
|
|
731
|
+
// At this point it is likely that we are stuck in a loop, so we stop here
|
|
732
|
+
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
733
|
+
message: JSON.stringify({
|
|
734
|
+
type: 'AskSkip',
|
|
735
|
+
status: 'Error',
|
|
736
|
+
conversationID: ConversationId,
|
|
737
|
+
message: 'Analysis failed to run, please try again later and if this continues, contact your support desk.',
|
|
738
|
+
}),
|
|
739
|
+
sessionId: userPayload.sessionId,
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
return {
|
|
743
|
+
Success: false,
|
|
744
|
+
Status: 'Error',
|
|
745
|
+
Result: `Exceeded maximum attempts to answer the question ${UserQuestion}`,
|
|
746
|
+
ResponsePhase: SkipResponsePhase.AnalysisComplete,
|
|
747
|
+
ConversationId: ConversationId,
|
|
748
|
+
UserMessageConversationDetailId: '',
|
|
749
|
+
AIMessageConversationDetailId: '',
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
|
|
684
753
|
const response = await sendPostRequest(
|
|
685
754
|
___skipAPIurl,
|
|
686
755
|
input,
|
|
@@ -736,7 +805,8 @@ export class AskSkipResolver {
|
|
|
736
805
|
convoEntity,
|
|
737
806
|
convoDetailEntity,
|
|
738
807
|
dataContext,
|
|
739
|
-
dataContextEntity
|
|
808
|
+
dataContextEntity,
|
|
809
|
+
conversationDetailCount
|
|
740
810
|
);
|
|
741
811
|
} else if (apiResponse.responsePhase === 'clarifying_question') {
|
|
742
812
|
// need to send the request back to the user for a clarifying question
|
|
@@ -925,7 +995,8 @@ export class AskSkipResolver {
|
|
|
925
995
|
convoEntity: ConversationEntity,
|
|
926
996
|
convoDetailEntity: ConversationDetailEntity,
|
|
927
997
|
dataContext: DataContext,
|
|
928
|
-
dataContextEntity: DataContextEntity
|
|
998
|
+
dataContextEntity: DataContextEntity,
|
|
999
|
+
conversationDetailCount: number
|
|
929
1000
|
): Promise<AskSkipResultType> {
|
|
930
1001
|
// our job in this method is to go through each of the data requests from the Skip API, get the data, and then go back to the Skip API again and to the next phase
|
|
931
1002
|
try {
|
|
@@ -1039,6 +1110,7 @@ export class AskSkipResolver {
|
|
|
1039
1110
|
apiRequest.dataContext = <DataContext>CopyScalarsAndArrays(dataContext); // we are casting this to DataContext as we're pushing this to the Skip API, and we don't want to send the real DataContext object, just a copy of the scalar and array properties
|
|
1040
1111
|
apiRequest.requestPhase = 'data_gathering_response';
|
|
1041
1112
|
}
|
|
1113
|
+
conversationDetailCount++;
|
|
1042
1114
|
// we have all of the data now, add it to the data context and then submit it back to the Skip API
|
|
1043
1115
|
return this.HandleSkipRequest(
|
|
1044
1116
|
apiRequest,
|
|
@@ -1052,7 +1124,8 @@ export class AskSkipResolver {
|
|
|
1052
1124
|
convoEntity,
|
|
1053
1125
|
convoDetailEntity,
|
|
1054
1126
|
dataContext,
|
|
1055
|
-
dataContextEntity
|
|
1127
|
+
dataContextEntity,
|
|
1128
|
+
conversationDetailCount
|
|
1056
1129
|
);
|
|
1057
1130
|
} catch (e) {
|
|
1058
1131
|
LogError(e);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Field, ObjectType, Query, Resolver } from 'type-graphql';
|
|
2
|
+
import { Public } from '../directives/index.js';
|
|
3
|
+
import packageJson from '../../package.json' assert { type: 'json' };
|
|
4
|
+
|
|
5
|
+
@ObjectType()
|
|
6
|
+
export class Info {
|
|
7
|
+
@Field(() => String)
|
|
8
|
+
@Public()
|
|
9
|
+
Version: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Resolver(Info)
|
|
13
|
+
export class InfoResolver {
|
|
14
|
+
@Query(() => Info)
|
|
15
|
+
@Public()
|
|
16
|
+
async Info() {
|
|
17
|
+
return { Version: packageJson.version };
|
|
18
|
+
}
|
|
19
|
+
}
|