@memberjunction/server 2.40.0 → 2.41.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/generated/generated.d.ts +8 -2
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +49 -18
- package/dist/generated/generated.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +8 -7
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +46 -15
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/package.json +22 -22
- package/src/generated/generated.ts +31 -12
- package/src/resolvers/AskSkipResolver.ts +80 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.41.0",
|
|
4
4
|
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -22,27 +22,27 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@apollo/server": "^4.9.1",
|
|
24
24
|
"@graphql-tools/utils": "^10.0.1",
|
|
25
|
-
"@memberjunction/actions": "2.
|
|
26
|
-
"@memberjunction/ai": "2.
|
|
27
|
-
"@memberjunction/ai-mistral": "2.
|
|
28
|
-
"@memberjunction/ai-openai": "2.
|
|
29
|
-
"@memberjunction/ai-vectors-pinecone": "2.
|
|
30
|
-
"@memberjunction/aiengine": "2.
|
|
31
|
-
"@memberjunction/core": "2.
|
|
32
|
-
"@memberjunction/core-actions": "2.
|
|
33
|
-
"@memberjunction/core-entities": "2.
|
|
34
|
-
"@memberjunction/data-context": "2.
|
|
35
|
-
"@memberjunction/data-context-server": "2.
|
|
36
|
-
"@memberjunction/doc-utils": "2.
|
|
37
|
-
"@memberjunction/entity-communications-server": "2.
|
|
38
|
-
"@memberjunction/external-change-detection": "2.
|
|
39
|
-
"@memberjunction/global": "2.
|
|
40
|
-
"@memberjunction/graphql-dataprovider": "2.
|
|
41
|
-
"@memberjunction/queue": "2.
|
|
42
|
-
"@memberjunction/skip-types": "2.
|
|
43
|
-
"@memberjunction/sqlserver-dataprovider": "2.
|
|
44
|
-
"@memberjunction/storage": "2.
|
|
45
|
-
"@memberjunction/templates": "2.
|
|
25
|
+
"@memberjunction/actions": "2.41.0",
|
|
26
|
+
"@memberjunction/ai": "2.41.0",
|
|
27
|
+
"@memberjunction/ai-mistral": "2.41.0",
|
|
28
|
+
"@memberjunction/ai-openai": "2.41.0",
|
|
29
|
+
"@memberjunction/ai-vectors-pinecone": "2.41.0",
|
|
30
|
+
"@memberjunction/aiengine": "2.41.0",
|
|
31
|
+
"@memberjunction/core": "2.41.0",
|
|
32
|
+
"@memberjunction/core-actions": "2.41.0",
|
|
33
|
+
"@memberjunction/core-entities": "2.41.0",
|
|
34
|
+
"@memberjunction/data-context": "2.41.0",
|
|
35
|
+
"@memberjunction/data-context-server": "2.41.0",
|
|
36
|
+
"@memberjunction/doc-utils": "2.41.0",
|
|
37
|
+
"@memberjunction/entity-communications-server": "2.41.0",
|
|
38
|
+
"@memberjunction/external-change-detection": "2.41.0",
|
|
39
|
+
"@memberjunction/global": "2.41.0",
|
|
40
|
+
"@memberjunction/graphql-dataprovider": "2.41.0",
|
|
41
|
+
"@memberjunction/queue": "2.41.0",
|
|
42
|
+
"@memberjunction/skip-types": "2.41.0",
|
|
43
|
+
"@memberjunction/sqlserver-dataprovider": "2.41.0",
|
|
44
|
+
"@memberjunction/storage": "2.41.0",
|
|
45
|
+
"@memberjunction/templates": "2.41.0",
|
|
46
46
|
"@types/compression": "^1.7.5",
|
|
47
47
|
"@types/cors": "^2.8.13",
|
|
48
48
|
"@types/jsonwebtoken": "9.0.6",
|
|
@@ -6271,15 +6271,15 @@ export class User_ {
|
|
|
6271
6271
|
@Field(() => [UserFavorite_])
|
|
6272
6272
|
UserFavorites_UserIDArray: UserFavorite_[]; // Link to UserFavorites
|
|
6273
6273
|
|
|
6274
|
-
@Field(() => [ResourceLink_])
|
|
6275
|
-
ResourceLinks_UserIDArray: ResourceLink_[]; // Link to ResourceLinks
|
|
6276
|
-
|
|
6277
6274
|
@Field(() => [ListCategory_])
|
|
6278
6275
|
ListCategories_UserIDArray: ListCategory_[]; // Link to ListCategories
|
|
6279
6276
|
|
|
6280
6277
|
@Field(() => [ScheduledAction_])
|
|
6281
6278
|
ScheduledActions_CreatedByUserIDArray: ScheduledAction_[]; // Link to ScheduledActions
|
|
6282
6279
|
|
|
6280
|
+
@Field(() => [ResourceLink_])
|
|
6281
|
+
ResourceLinks_UserIDArray: ResourceLink_[]; // Link to ResourceLinks
|
|
6282
|
+
|
|
6283
6283
|
@Field(() => [AIAgentRequest_])
|
|
6284
6284
|
AIAgentRequests_ResponseByUserIDArray: AIAgentRequest_[]; // Link to AIAgentRequests
|
|
6285
6285
|
|
|
@@ -6720,15 +6720,6 @@ export class UserResolverBase extends ResolverBase {
|
|
|
6720
6720
|
return result;
|
|
6721
6721
|
}
|
|
6722
6722
|
|
|
6723
|
-
@FieldResolver(() => [ResourceLink_])
|
|
6724
|
-
async ResourceLinks_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6725
|
-
this.CheckUserReadPermissions('Resource Links', userPayload);
|
|
6726
|
-
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
6727
|
-
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourceLinks] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Links', userPayload, EntityPermissionType.Read, 'AND');
|
|
6728
|
-
const result = this.ArrayMapFieldNamesToCodeNames('Resource Links', await dataSource.query(sSQL));
|
|
6729
|
-
return result;
|
|
6730
|
-
}
|
|
6731
|
-
|
|
6732
6723
|
@FieldResolver(() => [ListCategory_])
|
|
6733
6724
|
async ListCategories_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6734
6725
|
this.CheckUserReadPermissions('List Categories', userPayload);
|
|
@@ -6747,6 +6738,15 @@ export class UserResolverBase extends ResolverBase {
|
|
|
6747
6738
|
return result;
|
|
6748
6739
|
}
|
|
6749
6740
|
|
|
6741
|
+
@FieldResolver(() => [ResourceLink_])
|
|
6742
|
+
async ResourceLinks_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6743
|
+
this.CheckUserReadPermissions('Resource Links', userPayload);
|
|
6744
|
+
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
6745
|
+
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourceLinks] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Links', userPayload, EntityPermissionType.Read, 'AND');
|
|
6746
|
+
const result = this.ArrayMapFieldNamesToCodeNames('Resource Links', await dataSource.query(sSQL));
|
|
6747
|
+
return result;
|
|
6748
|
+
}
|
|
6749
|
+
|
|
6750
6750
|
@FieldResolver(() => [AIAgentRequest_])
|
|
6751
6751
|
async AIAgentRequests_ResponseByUserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6752
6752
|
this.CheckUserReadPermissions('AI Agent Requests', userPayload);
|
|
@@ -15717,6 +15717,9 @@ export class ConversationDetail_ {
|
|
|
15717
15717
|
@MaxLength(16)
|
|
15718
15718
|
ArtifactVersionID?: string;
|
|
15719
15719
|
|
|
15720
|
+
@Field(() => Int, {nullable: true, description: `Duration in milliseconds representing how long the AI response processing took to complete for this conversation detail.`})
|
|
15721
|
+
CompletionTime?: number;
|
|
15722
|
+
|
|
15720
15723
|
@Field({nullable: true})
|
|
15721
15724
|
@MaxLength(510)
|
|
15722
15725
|
Conversation?: string;
|
|
@@ -15777,6 +15780,9 @@ export class CreateConversationDetailInput {
|
|
|
15777
15780
|
|
|
15778
15781
|
@Field({ nullable: true })
|
|
15779
15782
|
ArtifactVersionID: string | null;
|
|
15783
|
+
|
|
15784
|
+
@Field(() => Int, { nullable: true })
|
|
15785
|
+
CompletionTime: number | null;
|
|
15780
15786
|
}
|
|
15781
15787
|
|
|
15782
15788
|
|
|
@@ -15827,6 +15833,9 @@ export class UpdateConversationDetailInput {
|
|
|
15827
15833
|
@Field({ nullable: true })
|
|
15828
15834
|
ArtifactVersionID?: string | null;
|
|
15829
15835
|
|
|
15836
|
+
@Field(() => Int, { nullable: true })
|
|
15837
|
+
CompletionTime?: number | null;
|
|
15838
|
+
|
|
15830
15839
|
@Field(() => [KeyValuePairInput], { nullable: true })
|
|
15831
15840
|
OldValues___?: KeyValuePairInput[];
|
|
15832
15841
|
}
|
|
@@ -15976,6 +15985,10 @@ export class Conversation_ {
|
|
|
15976
15985
|
@MaxLength(10)
|
|
15977
15986
|
_mj__UpdatedAt: Date;
|
|
15978
15987
|
|
|
15988
|
+
@Field({description: `Tracks the processing status of the conversation: Available, Processing`})
|
|
15989
|
+
@MaxLength(40)
|
|
15990
|
+
Status: string;
|
|
15991
|
+
|
|
15979
15992
|
@Field()
|
|
15980
15993
|
@MaxLength(200)
|
|
15981
15994
|
User: string;
|
|
@@ -16030,6 +16043,9 @@ export class CreateConversationInput {
|
|
|
16030
16043
|
|
|
16031
16044
|
@Field({ nullable: true })
|
|
16032
16045
|
DataContextID: string | null;
|
|
16046
|
+
|
|
16047
|
+
@Field({ nullable: true })
|
|
16048
|
+
Status?: string;
|
|
16033
16049
|
}
|
|
16034
16050
|
|
|
16035
16051
|
|
|
@@ -16068,6 +16084,9 @@ export class UpdateConversationInput {
|
|
|
16068
16084
|
@Field({ nullable: true })
|
|
16069
16085
|
DataContextID?: string | null;
|
|
16070
16086
|
|
|
16087
|
+
@Field({ nullable: true })
|
|
16088
|
+
Status?: string;
|
|
16089
|
+
|
|
16071
16090
|
@Field(() => [KeyValuePairInput], { nullable: true })
|
|
16072
16091
|
OldValues___?: KeyValuePairInput[];
|
|
16073
16092
|
}
|
|
@@ -63,7 +63,6 @@ import { CompositeKeyInputType } from '../generic/KeyInputOutputTypes.js';
|
|
|
63
63
|
import { AIAgentEntityExtended, AIEngine } from '@memberjunction/aiengine';
|
|
64
64
|
import { deleteAccessToken, GetDataAccessToken, registerAccessToken, tokenExists } from './GetDataResolver.js';
|
|
65
65
|
import e from 'express';
|
|
66
|
-
import { Skip } from '@graphql-tools/utils';
|
|
67
66
|
|
|
68
67
|
/**
|
|
69
68
|
* Enumeration representing the different phases of a Skip response
|
|
@@ -1323,12 +1322,16 @@ cycle.`);
|
|
|
1323
1322
|
@Ctx() { dataSource, userPayload }: AppContext,
|
|
1324
1323
|
@PubSub() pubSub: PubSubEngine,
|
|
1325
1324
|
@Arg('DataContextId', () => String, { nullable: true }) DataContextId?: string,
|
|
1326
|
-
@Arg('ForceEntityRefresh', () => Boolean, { nullable: true }) ForceEntityRefresh?: boolean
|
|
1325
|
+
@Arg('ForceEntityRefresh', () => Boolean, { nullable: true }) ForceEntityRefresh?: boolean,
|
|
1326
|
+
@Arg('StartTime', () => Date, { nullable: true }) StartTime?: Date
|
|
1327
1327
|
) {
|
|
1328
1328
|
const md = new Metadata();
|
|
1329
1329
|
const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
|
|
1330
1330
|
if (!user) throw new Error(`User ${userPayload.email} not found in UserCache`);
|
|
1331
1331
|
|
|
1332
|
+
// Record the start time if not provided
|
|
1333
|
+
const requestStartTime = StartTime || new Date();
|
|
1334
|
+
|
|
1332
1335
|
const { convoEntity, dataContextEntity, convoDetailEntity, dataContext } = await this.HandleSkipChatInitialObjectLoading(
|
|
1333
1336
|
dataSource,
|
|
1334
1337
|
ConversationId,
|
|
@@ -1339,6 +1342,9 @@ cycle.`);
|
|
|
1339
1342
|
DataContextId
|
|
1340
1343
|
);
|
|
1341
1344
|
|
|
1345
|
+
// Set the conversation status to 'Processing' when a request is initiated
|
|
1346
|
+
this.setConversationStatus(convoEntity, 'Processing');
|
|
1347
|
+
|
|
1342
1348
|
// now load up the messages. We will load up ALL of the messages for this conversation, and then pass them to the Skip API
|
|
1343
1349
|
const messages: SkipMessage[] = await this.LoadConversationDetailsIntoSkipMessages(
|
|
1344
1350
|
dataSource,
|
|
@@ -1363,6 +1369,7 @@ cycle.`);
|
|
|
1363
1369
|
dataContext,
|
|
1364
1370
|
dataContextEntity,
|
|
1365
1371
|
conversationDetailCount,
|
|
1372
|
+
requestStartTime
|
|
1366
1373
|
);
|
|
1367
1374
|
}
|
|
1368
1375
|
|
|
@@ -1843,6 +1850,8 @@ cycle.`);
|
|
|
1843
1850
|
if (user) {
|
|
1844
1851
|
convoEntity.UserID = user.ID;
|
|
1845
1852
|
convoEntity.Name = AskSkipResolver._defaultNewChatName;
|
|
1853
|
+
// Set initial status to Available since no processing has started yet
|
|
1854
|
+
convoEntity.Status = 'Available';
|
|
1846
1855
|
|
|
1847
1856
|
dataContextEntity = await md.GetEntityObject<DataContextEntity>('Data Contexts', user);
|
|
1848
1857
|
if (!DataContextId || DataContextId.length === 0) {
|
|
@@ -1957,7 +1966,8 @@ cycle.`);
|
|
|
1957
1966
|
protected async LoadConversationDetailsIntoSkipMessages(
|
|
1958
1967
|
dataSource: DataSource,
|
|
1959
1968
|
ConversationId: string,
|
|
1960
|
-
maxHistoricalMessages?: number
|
|
1969
|
+
maxHistoricalMessages?: number,
|
|
1970
|
+
roleFilter?: string
|
|
1961
1971
|
): Promise<SkipMessage[]> {
|
|
1962
1972
|
try {
|
|
1963
1973
|
if (!ConversationId || ConversationId.length === 0) {
|
|
@@ -1967,12 +1977,16 @@ cycle.`);
|
|
|
1967
1977
|
// load up all the conversation details from the database server
|
|
1968
1978
|
const md = new Metadata();
|
|
1969
1979
|
const e = md.Entities.find((e) => e.Name === 'Conversation Details');
|
|
1980
|
+
|
|
1981
|
+
// Add role filter if specified
|
|
1982
|
+
const roleFilterClause = roleFilter ? ` AND Role = '${roleFilter}'` : '';
|
|
1983
|
+
|
|
1970
1984
|
const sql = `SELECT
|
|
1971
1985
|
${maxHistoricalMessages ? 'TOP ' + maxHistoricalMessages : ''} *
|
|
1972
1986
|
FROM
|
|
1973
1987
|
${e.SchemaName}.${e.BaseView}
|
|
1974
1988
|
WHERE
|
|
1975
|
-
ConversationID = '${ConversationId}'
|
|
1989
|
+
ConversationID = '${ConversationId}'${roleFilterClause}
|
|
1976
1990
|
ORDER
|
|
1977
1991
|
BY __mj_CreatedAt DESC`;
|
|
1978
1992
|
const result = await dataSource.query(sql);
|
|
@@ -2095,12 +2109,16 @@ cycle.`);
|
|
|
2095
2109
|
convoDetailEntity: ConversationDetailEntity,
|
|
2096
2110
|
dataContext: DataContext,
|
|
2097
2111
|
dataContextEntity: DataContextEntity,
|
|
2098
|
-
conversationDetailCount: number
|
|
2112
|
+
conversationDetailCount: number,
|
|
2113
|
+
startTime: Date
|
|
2099
2114
|
): Promise<AskSkipResultType> {
|
|
2100
2115
|
const skipConfigInfo = configInfo.askSkip;
|
|
2101
2116
|
LogStatus(` >>> HandleSkipRequest: Sending request to Skip API: ${skipConfigInfo.chatURL}`);
|
|
2102
2117
|
|
|
2103
2118
|
if (conversationDetailCount > 10) {
|
|
2119
|
+
// Set status of conversation to Available since we still want to allow the user to ask questions
|
|
2120
|
+
await this.setConversationStatus(convoEntity, 'Available');
|
|
2121
|
+
|
|
2104
2122
|
// At this point it is likely that we are stuck in a loop, so we stop here
|
|
2105
2123
|
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
2106
2124
|
message: JSON.stringify({
|
|
@@ -2179,7 +2197,8 @@ cycle.`);
|
|
|
2179
2197
|
convoDetailEntity,
|
|
2180
2198
|
dataContext,
|
|
2181
2199
|
dataContextEntity,
|
|
2182
|
-
conversationDetailCount
|
|
2200
|
+
conversationDetailCount,
|
|
2201
|
+
startTime
|
|
2183
2202
|
);
|
|
2184
2203
|
} else if (apiResponse.responsePhase === 'clarifying_question') {
|
|
2185
2204
|
// need to send the request back to the user for a clarifying question
|
|
@@ -2193,7 +2212,8 @@ cycle.`);
|
|
|
2193
2212
|
userPayload,
|
|
2194
2213
|
pubSub,
|
|
2195
2214
|
convoEntity,
|
|
2196
|
-
convoDetailEntity
|
|
2215
|
+
convoDetailEntity,
|
|
2216
|
+
startTime,
|
|
2197
2217
|
);
|
|
2198
2218
|
} else if (apiResponse.responsePhase === 'analysis_complete') {
|
|
2199
2219
|
return await this.HandleAnalysisComplete(
|
|
@@ -2208,13 +2228,17 @@ cycle.`);
|
|
|
2208
2228
|
convoEntity,
|
|
2209
2229
|
convoDetailEntity,
|
|
2210
2230
|
dataContext,
|
|
2211
|
-
dataContextEntity
|
|
2231
|
+
dataContextEntity,
|
|
2232
|
+
startTime
|
|
2212
2233
|
);
|
|
2213
2234
|
} else {
|
|
2214
2235
|
// unknown response phase
|
|
2215
2236
|
throw new Error(`Unknown Skip API response phase: ${apiResponse.responsePhase}`);
|
|
2216
2237
|
}
|
|
2217
2238
|
} else {
|
|
2239
|
+
// Set status of conversation to Available since we still want to allow the user to ask questions
|
|
2240
|
+
await this.setConversationStatus(convoEntity, 'Available');
|
|
2241
|
+
|
|
2218
2242
|
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
2219
2243
|
message: JSON.stringify({
|
|
2220
2244
|
type: 'AskSkip',
|
|
@@ -2308,7 +2332,8 @@ cycle.`);
|
|
|
2308
2332
|
convoEntity: ConversationEntity,
|
|
2309
2333
|
convoDetailEntity: ConversationDetailEntity,
|
|
2310
2334
|
dataContext: DataContext,
|
|
2311
|
-
dataContextEntity: DataContextEntity
|
|
2335
|
+
dataContextEntity: DataContextEntity,
|
|
2336
|
+
startTime: Date
|
|
2312
2337
|
): Promise<AskSkipResultType> {
|
|
2313
2338
|
// analysis is complete
|
|
2314
2339
|
// all done, wrap things up
|
|
@@ -2328,7 +2353,8 @@ cycle.`);
|
|
|
2328
2353
|
convoEntity,
|
|
2329
2354
|
pubSub,
|
|
2330
2355
|
userPayload,
|
|
2331
|
-
dataSource
|
|
2356
|
+
dataSource,
|
|
2357
|
+
startTime
|
|
2332
2358
|
);
|
|
2333
2359
|
const response: AskSkipResultType = {
|
|
2334
2360
|
Success: true,
|
|
@@ -2368,9 +2394,11 @@ cycle.`);
|
|
|
2368
2394
|
userPayload: UserPayload,
|
|
2369
2395
|
pubSub: PubSubEngine,
|
|
2370
2396
|
convoEntity: ConversationEntity,
|
|
2371
|
-
convoDetailEntity: ConversationDetailEntity
|
|
2397
|
+
convoDetailEntity: ConversationDetailEntity,
|
|
2398
|
+
startTime: Date
|
|
2372
2399
|
): Promise<AskSkipResultType> {
|
|
2373
2400
|
// need to create a message here in the COnversation and then pass that id below
|
|
2401
|
+
const endTime = new Date();
|
|
2374
2402
|
const md = new Metadata();
|
|
2375
2403
|
const convoDetailEntityAI = <ConversationDetailEntity>await md.GetEntityObject('Conversation Details', user);
|
|
2376
2404
|
convoDetailEntityAI.NewRecord();
|
|
@@ -2378,6 +2406,11 @@ cycle.`);
|
|
|
2378
2406
|
convoDetailEntityAI.Message = JSON.stringify(apiResponse); //.clarifyingQuestion;
|
|
2379
2407
|
convoDetailEntityAI.Role = 'AI';
|
|
2380
2408
|
convoDetailEntityAI.HiddenToUser = false;
|
|
2409
|
+
convoDetailEntityAI.CompletionTime = endTime.getTime() - startTime.getTime();
|
|
2410
|
+
|
|
2411
|
+
// Set conversation status back to Available since we need user input for the clarifying question
|
|
2412
|
+
this.setConversationStatus(convoEntity, 'Available');
|
|
2413
|
+
|
|
2381
2414
|
if (await convoDetailEntityAI.Save()) {
|
|
2382
2415
|
return {
|
|
2383
2416
|
Success: true,
|
|
@@ -2438,7 +2471,8 @@ cycle.`);
|
|
|
2438
2471
|
convoDetailEntity: ConversationDetailEntity,
|
|
2439
2472
|
dataContext: DataContext,
|
|
2440
2473
|
dataContextEntity: DataContextEntity,
|
|
2441
|
-
conversationDetailCount: number
|
|
2474
|
+
conversationDetailCount: number,
|
|
2475
|
+
startTime: Date
|
|
2442
2476
|
): Promise<AskSkipResultType> {
|
|
2443
2477
|
// 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
|
|
2444
2478
|
try {
|
|
@@ -2567,7 +2601,8 @@ cycle.`);
|
|
|
2567
2601
|
convoDetailEntity,
|
|
2568
2602
|
dataContext,
|
|
2569
2603
|
dataContextEntity,
|
|
2570
|
-
conversationDetailCount
|
|
2604
|
+
conversationDetailCount,
|
|
2605
|
+
startTime
|
|
2571
2606
|
);
|
|
2572
2607
|
} catch (e) {
|
|
2573
2608
|
LogError(e);
|
|
@@ -2599,7 +2634,8 @@ cycle.`);
|
|
|
2599
2634
|
convoEntity: ConversationEntity,
|
|
2600
2635
|
pubSub: PubSubEngine,
|
|
2601
2636
|
userPayload: UserPayload,
|
|
2602
|
-
dataSource: DataSource
|
|
2637
|
+
dataSource: DataSource,
|
|
2638
|
+
startTime: Date
|
|
2603
2639
|
): Promise<{ AIMessageConversationDetailID: string }> {
|
|
2604
2640
|
const sTitle = apiResponse.reportTitle;
|
|
2605
2641
|
const sResult = JSON.stringify(apiResponse);
|
|
@@ -2670,12 +2706,15 @@ cycle.`);
|
|
|
2670
2706
|
}
|
|
2671
2707
|
|
|
2672
2708
|
// Create a conversation detail record for the Skip response
|
|
2709
|
+
const endTime = new Date();
|
|
2673
2710
|
const convoDetailEntityAI = <ConversationDetailEntity>await md.GetEntityObject('Conversation Details', user);
|
|
2674
2711
|
convoDetailEntityAI.NewRecord();
|
|
2675
2712
|
convoDetailEntityAI.ConversationID = convoEntity.ID;
|
|
2676
2713
|
convoDetailEntityAI.Message = sResult;
|
|
2677
2714
|
convoDetailEntityAI.Role = 'AI';
|
|
2678
2715
|
convoDetailEntityAI.HiddenToUser = false;
|
|
2716
|
+
convoDetailEntityAI.CompletionTime = endTime.getTime() - startTime.getTime();
|
|
2717
|
+
|
|
2679
2718
|
if (artifactId && artifactId.length > 0) {
|
|
2680
2719
|
// bind the new convo detail record to the artifact + version for this response
|
|
2681
2720
|
convoDetailEntityAI.ArtifactID = artifactId;
|
|
@@ -2688,9 +2727,23 @@ cycle.`);
|
|
|
2688
2727
|
LogError(`Error saving conversation detail entity for AI message: ${sResult}`, undefined, convoDetailEntityAI.LatestResult);
|
|
2689
2728
|
}
|
|
2690
2729
|
|
|
2691
|
-
//
|
|
2730
|
+
// Update the conversation properties: name if it's the default, and set status back to 'Available'
|
|
2731
|
+
let needToSaveConvo = false;
|
|
2732
|
+
|
|
2733
|
+
// Update name if still default
|
|
2692
2734
|
if (convoEntity.Name === AskSkipResolver._defaultNewChatName && sTitle && sTitle !== AskSkipResolver._defaultNewChatName) {
|
|
2693
2735
|
convoEntity.Name = sTitle; // use the title from the response
|
|
2736
|
+
needToSaveConvo = true;
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
// Set status back to 'Available' since processing is complete
|
|
2740
|
+
if (convoEntity.Status === 'Processing') {
|
|
2741
|
+
convoEntity.Status = 'Available';
|
|
2742
|
+
needToSaveConvo = true;
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
// Save if any changes were made
|
|
2746
|
+
if (needToSaveConvo) {
|
|
2694
2747
|
const convoEntitySaveResult: boolean = await convoEntity.Save();
|
|
2695
2748
|
if (!convoEntitySaveResult) {
|
|
2696
2749
|
LogError(`Error saving conversation entity for AI message: ${sResult}`, undefined, convoEntity.LatestResult);
|
|
@@ -2749,6 +2802,18 @@ cycle.`);
|
|
|
2749
2802
|
};
|
|
2750
2803
|
}
|
|
2751
2804
|
|
|
2805
|
+
private async setConversationStatus(convoEntity: ConversationEntity, status: 'Processing' | 'Available'): Promise<boolean> {
|
|
2806
|
+
if (convoEntity.Status !== status) {
|
|
2807
|
+
convoEntity.Status = status;
|
|
2808
|
+
const convoSaveResult = await convoEntity.Save();
|
|
2809
|
+
if (!convoSaveResult) {
|
|
2810
|
+
LogError(`Error updating conversation status to '${status}'`, undefined, convoEntity.LatestResult);
|
|
2811
|
+
}
|
|
2812
|
+
return convoSaveResult;
|
|
2813
|
+
}
|
|
2814
|
+
return true;
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2752
2817
|
/**
|
|
2753
2818
|
* Gets the ID of an agent note type by its name
|
|
2754
2819
|
* Falls back to a default note type if the specified one is not found
|