@memberjunction/server 3.2.0 → 3.4.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 +106 -1
- package/dist/auth/APIKeyScopeAuth.d.ts +51 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -0
- package/dist/auth/APIKeyScopeAuth.js +163 -0
- package/dist/auth/APIKeyScopeAuth.js.map +1 -0
- package/dist/auth/BaseAuthProvider.d.ts +1 -0
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/BaseAuthProvider.js +2 -0
- package/dist/auth/BaseAuthProvider.js.map +1 -1
- package/dist/auth/IAuthProvider.d.ts +1 -0
- package/dist/auth/IAuthProvider.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +8 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +44 -7
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +681 -2
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +10627 -6409
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +3 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +52 -4
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +29 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +143 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/resolvers/APIKeyResolver.d.ts +24 -0
- package/dist/resolvers/APIKeyResolver.d.ts.map +1 -0
- package/dist/resolvers/APIKeyResolver.js +194 -0
- package/dist/resolvers/APIKeyResolver.js.map +1 -0
- package/dist/resolvers/ActionResolver.d.ts +2 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +4 -1
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +5 -4
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +7 -4
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +2 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +3 -1
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +2 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +10 -3
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +37 -0
- package/dist/resolvers/MCPResolver.d.ts.map +1 -0
- package/dist/resolvers/MCPResolver.js +363 -0
- package/dist/resolvers/MCPResolver.js.map +1 -0
- package/dist/resolvers/MergeRecordsResolver.d.ts +2 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +3 -1
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +2 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +6 -1
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.d.ts +2 -1
- package/dist/resolvers/ReportResolver.d.ts.map +1 -1
- package/dist/resolvers/ReportResolver.js +4 -1
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +3 -1
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +3 -0
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +1 -0
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskResolver.js +1 -0
- package/dist/resolvers/TaskResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +35 -1
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/types.d.ts +4 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +47 -45
- package/src/auth/APIKeyScopeAuth.ts +366 -0
- package/src/auth/BaseAuthProvider.ts +3 -0
- package/src/auth/IAuthProvider.ts +5 -0
- package/src/auth/index.ts +1 -0
- package/src/config.ts +2 -2
- package/src/context.ts +91 -9
- package/src/generated/generated.ts +6327 -3668
- package/src/generic/ResolverBase.ts +127 -8
- package/src/generic/RunViewResolver.ts +132 -5
- package/src/index.ts +12 -2
- package/src/resolvers/APIKeyResolver.ts +241 -0
- package/src/resolvers/ActionResolver.ts +8 -1
- package/src/resolvers/DatasetResolver.ts +11 -4
- package/src/resolvers/EntityCommunicationsResolver.ts +5 -1
- package/src/resolvers/GetDataContextDataResolver.ts +14 -6
- package/src/resolvers/MCPResolver.ts +480 -0
- package/src/resolvers/MergeRecordsResolver.ts +5 -1
- package/src/resolvers/QueryResolver.ts +17 -3
- package/src/resolvers/ReportResolver.ts +8 -1
- package/src/resolvers/RunAIAgentResolver.ts +7 -1
- package/src/resolvers/RunAIPromptResolver.ts +10 -1
- package/src/resolvers/RunTemplateResolver.ts +4 -1
- package/src/resolvers/TaskResolver.ts +3 -0
- package/src/resolvers/UserResolver.ts +52 -4
- package/src/types.ts +7 -2
- 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
- package/src/resolvers/AskSkipResolver.ts +0 -3446
- package/src/scheduler/LearningCycleScheduler.ts +0 -320
|
@@ -1,1788 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
-
};
|
|
13
|
-
var AskSkipResolver_1;
|
|
14
|
-
import { Arg, Ctx, Field, ObjectType, PubSub, PubSubEngine, Query, Resolver } from 'type-graphql';
|
|
15
|
-
import { LogError, LogStatus, Metadata, RunView, CompositeKey } from '@memberjunction/core';
|
|
16
|
-
import { BehaviorSubject } from 'rxjs';
|
|
17
|
-
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
18
|
-
import { DataContext } from '@memberjunction/data-context';
|
|
19
|
-
import { LoadDataContextItemsServer } from '@memberjunction/data-context-server';
|
|
20
|
-
LoadDataContextItemsServer();
|
|
21
|
-
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
|
|
22
|
-
import { apiKey as callbackAPIKey, baseUrl, publicUrl, configInfo, graphqlPort, graphqlRootPath } from '../config.js';
|
|
23
|
-
import mssql from 'mssql';
|
|
24
|
-
import { registerEnumType } from 'type-graphql';
|
|
25
|
-
import { MJGlobal, CopyScalarsAndArrays } from '@memberjunction/global';
|
|
26
|
-
import { GetReadWriteProvider, sendPostRequest } from '../util.js';
|
|
27
|
-
import { GetAIAPIKey } from '@memberjunction/ai';
|
|
28
|
-
import { CompositeKeyInputType } from '../generic/KeyInputOutputTypes.js';
|
|
29
|
-
import { AIEngine } from '@memberjunction/aiengine';
|
|
30
|
-
import { deleteAccessToken, registerAccessToken, tokenExists } from './GetDataResolver.js';
|
|
31
|
-
const SKIP_API_ENDPOINTS = {
|
|
32
|
-
CHAT: '/chat',
|
|
33
|
-
LEARNING: '/learning',
|
|
34
|
-
FEEDBACK_COMPONENT: '/feedback/component',
|
|
35
|
-
REGISTRY: '/registry',
|
|
36
|
-
};
|
|
37
|
-
class ActiveConversationStreams {
|
|
38
|
-
static instance;
|
|
39
|
-
streams = new Map();
|
|
40
|
-
constructor() { }
|
|
41
|
-
static getInstance() {
|
|
42
|
-
if (!ActiveConversationStreams.instance) {
|
|
43
|
-
ActiveConversationStreams.instance = new ActiveConversationStreams();
|
|
44
|
-
}
|
|
45
|
-
return ActiveConversationStreams.instance;
|
|
46
|
-
}
|
|
47
|
-
updateStatus(conversationId, status, sessionId) {
|
|
48
|
-
const existing = this.streams.get(conversationId);
|
|
49
|
-
if (existing) {
|
|
50
|
-
existing.lastStatus = status;
|
|
51
|
-
existing.lastUpdate = new Date();
|
|
52
|
-
if (sessionId) {
|
|
53
|
-
existing.sessionIds.add(sessionId);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
const now = new Date();
|
|
58
|
-
this.streams.set(conversationId, {
|
|
59
|
-
lastStatus: status,
|
|
60
|
-
lastUpdate: now,
|
|
61
|
-
startTime: now,
|
|
62
|
-
sessionIds: sessionId ? new Set([sessionId]) : new Set()
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
getStatus(conversationId) {
|
|
67
|
-
const stream = this.streams.get(conversationId);
|
|
68
|
-
return stream ? stream.lastStatus : null;
|
|
69
|
-
}
|
|
70
|
-
getStartTime(conversationId) {
|
|
71
|
-
const stream = this.streams.get(conversationId);
|
|
72
|
-
return stream ? stream.startTime : null;
|
|
73
|
-
}
|
|
74
|
-
addSession(conversationId, sessionId) {
|
|
75
|
-
const stream = this.streams.get(conversationId);
|
|
76
|
-
if (stream) {
|
|
77
|
-
stream.sessionIds.add(sessionId);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
const now = new Date();
|
|
81
|
-
this.streams.set(conversationId, {
|
|
82
|
-
lastStatus: 'Processing...',
|
|
83
|
-
lastUpdate: now,
|
|
84
|
-
startTime: now,
|
|
85
|
-
sessionIds: new Set([sessionId])
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
removeConversation(conversationId) {
|
|
90
|
-
this.streams.delete(conversationId);
|
|
91
|
-
}
|
|
92
|
-
isActive(conversationId) {
|
|
93
|
-
const stream = this.streams.get(conversationId);
|
|
94
|
-
if (!stream)
|
|
95
|
-
return false;
|
|
96
|
-
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
|
|
97
|
-
return stream.lastUpdate > fiveMinutesAgo;
|
|
98
|
-
}
|
|
99
|
-
getSessionIds(conversationId) {
|
|
100
|
-
const stream = this.streams.get(conversationId);
|
|
101
|
-
return stream ? Array.from(stream.sessionIds) : [];
|
|
102
|
-
}
|
|
103
|
-
cleanupStaleStreams() {
|
|
104
|
-
const now = new Date();
|
|
105
|
-
const staleThreshold = new Date(now.getTime() - 30 * 60 * 1000);
|
|
106
|
-
const staleConversations = [];
|
|
107
|
-
this.streams.forEach((stream, conversationId) => {
|
|
108
|
-
if (stream.lastUpdate < staleThreshold) {
|
|
109
|
-
staleConversations.push(conversationId);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
staleConversations.forEach(conversationId => {
|
|
113
|
-
this.streams.delete(conversationId);
|
|
114
|
-
LogStatus(`Cleaned up stale stream for conversation ${conversationId}`);
|
|
115
|
-
});
|
|
116
|
-
if (staleConversations.length > 0) {
|
|
117
|
-
LogStatus(`Cleaned up ${staleConversations.length} stale conversation streams`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
const activeStreams = ActiveConversationStreams.getInstance();
|
|
122
|
-
setInterval(() => {
|
|
123
|
-
activeStreams.cleanupStaleStreams();
|
|
124
|
-
}, 10 * 60 * 1000);
|
|
125
|
-
let ReattachConversationResponse = class ReattachConversationResponse {
|
|
126
|
-
lastStatusMessage;
|
|
127
|
-
startTime;
|
|
128
|
-
};
|
|
129
|
-
__decorate([
|
|
130
|
-
Field(() => String, { nullable: true }),
|
|
131
|
-
__metadata("design:type", String)
|
|
132
|
-
], ReattachConversationResponse.prototype, "lastStatusMessage", void 0);
|
|
133
|
-
__decorate([
|
|
134
|
-
Field(() => Date, { nullable: true }),
|
|
135
|
-
__metadata("design:type", Date)
|
|
136
|
-
], ReattachConversationResponse.prototype, "startTime", void 0);
|
|
137
|
-
ReattachConversationResponse = __decorate([
|
|
138
|
-
ObjectType()
|
|
139
|
-
], ReattachConversationResponse);
|
|
140
|
-
var SkipResponsePhase;
|
|
141
|
-
(function (SkipResponsePhase) {
|
|
142
|
-
SkipResponsePhase["ClarifyingQuestion"] = "clarifying_question";
|
|
143
|
-
SkipResponsePhase["DataRequest"] = "data_request";
|
|
144
|
-
SkipResponsePhase["AnalysisComplete"] = "analysis_complete";
|
|
145
|
-
})(SkipResponsePhase || (SkipResponsePhase = {}));
|
|
146
|
-
registerEnumType(SkipResponsePhase, {
|
|
147
|
-
name: 'SkipResponsePhase',
|
|
148
|
-
description: 'The phase of the respons: clarifying_question, data_request, or analysis_complete',
|
|
149
|
-
});
|
|
150
|
-
let AskSkipResultType = class AskSkipResultType {
|
|
151
|
-
Success;
|
|
152
|
-
Status;
|
|
153
|
-
ResponsePhase;
|
|
154
|
-
Result;
|
|
155
|
-
ConversationId;
|
|
156
|
-
UserMessageConversationDetailId;
|
|
157
|
-
AIMessageConversationDetailId;
|
|
158
|
-
};
|
|
159
|
-
__decorate([
|
|
160
|
-
Field(() => Boolean),
|
|
161
|
-
__metadata("design:type", Boolean)
|
|
162
|
-
], AskSkipResultType.prototype, "Success", void 0);
|
|
163
|
-
__decorate([
|
|
164
|
-
Field(() => String),
|
|
165
|
-
__metadata("design:type", String)
|
|
166
|
-
], AskSkipResultType.prototype, "Status", void 0);
|
|
167
|
-
__decorate([
|
|
168
|
-
Field(() => SkipResponsePhase),
|
|
169
|
-
__metadata("design:type", String)
|
|
170
|
-
], AskSkipResultType.prototype, "ResponsePhase", void 0);
|
|
171
|
-
__decorate([
|
|
172
|
-
Field(() => String),
|
|
173
|
-
__metadata("design:type", String)
|
|
174
|
-
], AskSkipResultType.prototype, "Result", void 0);
|
|
175
|
-
__decorate([
|
|
176
|
-
Field(() => String),
|
|
177
|
-
__metadata("design:type", String)
|
|
178
|
-
], AskSkipResultType.prototype, "ConversationId", void 0);
|
|
179
|
-
__decorate([
|
|
180
|
-
Field(() => String),
|
|
181
|
-
__metadata("design:type", String)
|
|
182
|
-
], AskSkipResultType.prototype, "UserMessageConversationDetailId", void 0);
|
|
183
|
-
__decorate([
|
|
184
|
-
Field(() => String),
|
|
185
|
-
__metadata("design:type", String)
|
|
186
|
-
], AskSkipResultType.prototype, "AIMessageConversationDetailId", void 0);
|
|
187
|
-
AskSkipResultType = __decorate([
|
|
188
|
-
ObjectType()
|
|
189
|
-
], AskSkipResultType);
|
|
190
|
-
export { AskSkipResultType };
|
|
191
|
-
let ManualLearningCycleResultType = class ManualLearningCycleResultType {
|
|
192
|
-
Success;
|
|
193
|
-
Message;
|
|
194
|
-
};
|
|
195
|
-
__decorate([
|
|
196
|
-
Field(() => Boolean),
|
|
197
|
-
__metadata("design:type", Boolean)
|
|
198
|
-
], ManualLearningCycleResultType.prototype, "Success", void 0);
|
|
199
|
-
__decorate([
|
|
200
|
-
Field(() => String),
|
|
201
|
-
__metadata("design:type", String)
|
|
202
|
-
], ManualLearningCycleResultType.prototype, "Message", void 0);
|
|
203
|
-
ManualLearningCycleResultType = __decorate([
|
|
204
|
-
ObjectType()
|
|
205
|
-
], ManualLearningCycleResultType);
|
|
206
|
-
export { ManualLearningCycleResultType };
|
|
207
|
-
let CycleDetailsType = class CycleDetailsType {
|
|
208
|
-
LearningCycleId;
|
|
209
|
-
StartTime;
|
|
210
|
-
RunningForMinutes;
|
|
211
|
-
};
|
|
212
|
-
__decorate([
|
|
213
|
-
Field(() => String),
|
|
214
|
-
__metadata("design:type", String)
|
|
215
|
-
], CycleDetailsType.prototype, "LearningCycleId", void 0);
|
|
216
|
-
__decorate([
|
|
217
|
-
Field(() => String),
|
|
218
|
-
__metadata("design:type", String)
|
|
219
|
-
], CycleDetailsType.prototype, "StartTime", void 0);
|
|
220
|
-
__decorate([
|
|
221
|
-
Field(() => Number),
|
|
222
|
-
__metadata("design:type", Number)
|
|
223
|
-
], CycleDetailsType.prototype, "RunningForMinutes", void 0);
|
|
224
|
-
CycleDetailsType = __decorate([
|
|
225
|
-
ObjectType()
|
|
226
|
-
], CycleDetailsType);
|
|
227
|
-
export { CycleDetailsType };
|
|
228
|
-
let RunningOrganizationType = class RunningOrganizationType {
|
|
229
|
-
OrganizationId;
|
|
230
|
-
LearningCycleId;
|
|
231
|
-
StartTime;
|
|
232
|
-
RunningForMinutes;
|
|
233
|
-
};
|
|
234
|
-
__decorate([
|
|
235
|
-
Field(() => String),
|
|
236
|
-
__metadata("design:type", String)
|
|
237
|
-
], RunningOrganizationType.prototype, "OrganizationId", void 0);
|
|
238
|
-
__decorate([
|
|
239
|
-
Field(() => String),
|
|
240
|
-
__metadata("design:type", String)
|
|
241
|
-
], RunningOrganizationType.prototype, "LearningCycleId", void 0);
|
|
242
|
-
__decorate([
|
|
243
|
-
Field(() => String),
|
|
244
|
-
__metadata("design:type", String)
|
|
245
|
-
], RunningOrganizationType.prototype, "StartTime", void 0);
|
|
246
|
-
__decorate([
|
|
247
|
-
Field(() => Number),
|
|
248
|
-
__metadata("design:type", Number)
|
|
249
|
-
], RunningOrganizationType.prototype, "RunningForMinutes", void 0);
|
|
250
|
-
RunningOrganizationType = __decorate([
|
|
251
|
-
ObjectType()
|
|
252
|
-
], RunningOrganizationType);
|
|
253
|
-
export { RunningOrganizationType };
|
|
254
|
-
let LearningCycleStatusType = class LearningCycleStatusType {
|
|
255
|
-
IsSchedulerRunning;
|
|
256
|
-
LastRunTime;
|
|
257
|
-
RunningOrganizations;
|
|
258
|
-
};
|
|
259
|
-
__decorate([
|
|
260
|
-
Field(() => Boolean),
|
|
261
|
-
__metadata("design:type", Boolean)
|
|
262
|
-
], LearningCycleStatusType.prototype, "IsSchedulerRunning", void 0);
|
|
263
|
-
__decorate([
|
|
264
|
-
Field(() => String, { nullable: true }),
|
|
265
|
-
__metadata("design:type", String)
|
|
266
|
-
], LearningCycleStatusType.prototype, "LastRunTime", void 0);
|
|
267
|
-
__decorate([
|
|
268
|
-
Field(() => [RunningOrganizationType], { nullable: true }),
|
|
269
|
-
__metadata("design:type", Array)
|
|
270
|
-
], LearningCycleStatusType.prototype, "RunningOrganizations", void 0);
|
|
271
|
-
LearningCycleStatusType = __decorate([
|
|
272
|
-
ObjectType()
|
|
273
|
-
], LearningCycleStatusType);
|
|
274
|
-
export { LearningCycleStatusType };
|
|
275
|
-
let StopLearningCycleResultType = class StopLearningCycleResultType {
|
|
276
|
-
Success;
|
|
277
|
-
Message;
|
|
278
|
-
WasRunning;
|
|
279
|
-
CycleDetails;
|
|
280
|
-
};
|
|
281
|
-
__decorate([
|
|
282
|
-
Field(() => Boolean),
|
|
283
|
-
__metadata("design:type", Boolean)
|
|
284
|
-
], StopLearningCycleResultType.prototype, "Success", void 0);
|
|
285
|
-
__decorate([
|
|
286
|
-
Field(() => String),
|
|
287
|
-
__metadata("design:type", String)
|
|
288
|
-
], StopLearningCycleResultType.prototype, "Message", void 0);
|
|
289
|
-
__decorate([
|
|
290
|
-
Field(() => Boolean),
|
|
291
|
-
__metadata("design:type", Boolean)
|
|
292
|
-
], StopLearningCycleResultType.prototype, "WasRunning", void 0);
|
|
293
|
-
__decorate([
|
|
294
|
-
Field(() => CycleDetailsType, { nullable: true }),
|
|
295
|
-
__metadata("design:type", CycleDetailsType)
|
|
296
|
-
], StopLearningCycleResultType.prototype, "CycleDetails", void 0);
|
|
297
|
-
StopLearningCycleResultType = __decorate([
|
|
298
|
-
ObjectType()
|
|
299
|
-
], StopLearningCycleResultType);
|
|
300
|
-
export { StopLearningCycleResultType };
|
|
301
|
-
let AskSkipResolver = class AskSkipResolver {
|
|
302
|
-
static { AskSkipResolver_1 = this; }
|
|
303
|
-
static _defaultNewChatName = 'New Chat';
|
|
304
|
-
static _maxHistoricalMessages = 30;
|
|
305
|
-
async ExecuteAskSkipRecordChat(UserQuestion, ConversationId, EntityName, compositeKey, { dataSource, userPayload, providers }, pubSub) {
|
|
306
|
-
const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
|
|
307
|
-
if (!user)
|
|
308
|
-
throw new Error(`User ${userPayload.email} not found in UserCache`);
|
|
309
|
-
let messages = [];
|
|
310
|
-
if (ConversationId && ConversationId.length > 0) {
|
|
311
|
-
messages = await this.LoadConversationDetailsIntoSkipMessages(dataSource, ConversationId, AskSkipResolver_1._maxHistoricalMessages);
|
|
312
|
-
}
|
|
313
|
-
const md = GetReadWriteProvider(providers);
|
|
314
|
-
const { convoEntity, dataContextEntity, convoDetailEntity, dataContext } = await this.HandleSkipChatInitialObjectLoading(dataSource, ConversationId, UserQuestion, user, userPayload, md, null);
|
|
315
|
-
if (!ConversationId || ConversationId.length === 0) {
|
|
316
|
-
const dci = await md.GetEntityObject('Data Context Items', user);
|
|
317
|
-
dci.DataContextID = dataContext.ID;
|
|
318
|
-
dci.Type = 'single_record';
|
|
319
|
-
dci.EntityID = md.Entities.find((e) => e.Name === EntityName)?.ID;
|
|
320
|
-
const ck = new CompositeKey();
|
|
321
|
-
ck.KeyValuePairs = compositeKey.KeyValuePairs;
|
|
322
|
-
dci.RecordID = ck.Values();
|
|
323
|
-
let dciSaveResult = await dci.Save();
|
|
324
|
-
if (!dciSaveResult) {
|
|
325
|
-
LogError(`Error saving DataContextItemEntity for record chat: ${EntityName} ${ck.Values()}`, undefined, dci.LatestResult);
|
|
326
|
-
}
|
|
327
|
-
await dataContext.Load(dataContext.ID, dataSource, false, true, 10, user);
|
|
328
|
-
await dataContext.SaveItems(user, true);
|
|
329
|
-
convoEntity.LinkedEntityID = dci.EntityID;
|
|
330
|
-
convoEntity.LinkedRecordID = ck.Values();
|
|
331
|
-
convoEntity.DataContextID = dataContext.ID;
|
|
332
|
-
const convoEntitySaveResult = await convoEntity.Save();
|
|
333
|
-
if (!convoEntitySaveResult) {
|
|
334
|
-
LogError(`Error saving ConversationEntity for record chat: ${EntityName} ${ck.Values()}`, undefined, convoEntity.LatestResult);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
const input = await this.buildSkipChatAPIRequest(messages, ConversationId, dataContext, 'chat_with_a_record', false, false, false, false, user, dataSource, false, false);
|
|
338
|
-
messages.push({
|
|
339
|
-
content: UserQuestion,
|
|
340
|
-
role: 'user',
|
|
341
|
-
conversationDetailID: convoDetailEntity.ID,
|
|
342
|
-
});
|
|
343
|
-
return this.handleSimpleSkipChatPostRequest(input, convoEntity, convoDetailEntity, true, user, userPayload);
|
|
344
|
-
}
|
|
345
|
-
async handleSimpleSkipChatPostRequest(input, convoEntity = null, convoDetailEntity = null, createAIMessageConversationDetail = false, user = null, userPayload = null) {
|
|
346
|
-
const skipConfigInfo = configInfo.askSkip;
|
|
347
|
-
const chatURL = skipConfigInfo.url ? `${skipConfigInfo.url}${SKIP_API_ENDPOINTS.CHAT}` : skipConfigInfo.chatURL;
|
|
348
|
-
LogStatus(` >>> HandleSimpleSkipChatPostRequest Sending request to Skip API: ${chatURL}`);
|
|
349
|
-
try {
|
|
350
|
-
const response = await sendPostRequest(chatURL, input, true, this.buildSkipPostHeaders());
|
|
351
|
-
if (response && response.length > 0) {
|
|
352
|
-
const apiResponse = response[response.length - 1].value;
|
|
353
|
-
const AIMessageConversationDetailID = createAIMessageConversationDetail && convoEntity
|
|
354
|
-
? await this.CreateAIMessageConversationDetail(apiResponse, convoEntity.ID, user, userPayload)
|
|
355
|
-
: '';
|
|
356
|
-
LogStatus(` Skip API response: ${apiResponse.responsePhase}`);
|
|
357
|
-
return {
|
|
358
|
-
Success: true,
|
|
359
|
-
Status: 'OK',
|
|
360
|
-
ResponsePhase: SkipResponsePhase.AnalysisComplete,
|
|
361
|
-
ConversationId: convoEntity ? convoEntity.ID : '',
|
|
362
|
-
UserMessageConversationDetailId: convoDetailEntity ? convoDetailEntity.ID : '',
|
|
363
|
-
AIMessageConversationDetailId: AIMessageConversationDetailID,
|
|
364
|
-
Result: JSON.stringify(apiResponse),
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
if (convoEntity) {
|
|
369
|
-
await this.setConversationStatus(convoEntity, 'Available', userPayload);
|
|
370
|
-
}
|
|
371
|
-
return {
|
|
372
|
-
Success: false,
|
|
373
|
-
Status: 'Error',
|
|
374
|
-
Result: `Request failed`,
|
|
375
|
-
ResponsePhase: SkipResponsePhase.AnalysisComplete,
|
|
376
|
-
ConversationId: convoEntity ? convoEntity.ID : '',
|
|
377
|
-
UserMessageConversationDetailId: convoDetailEntity ? convoDetailEntity.ID : '',
|
|
378
|
-
AIMessageConversationDetailId: '',
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
catch (error) {
|
|
383
|
-
if (convoEntity) {
|
|
384
|
-
await this.setConversationStatus(convoEntity, 'Available', userPayload);
|
|
385
|
-
}
|
|
386
|
-
LogError(`Error in handleSimpleSkipChatPostRequest: ${error}`);
|
|
387
|
-
throw error;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
async CreateAIMessageConversationDetail(apiResponse, conversationID, user, userPayload) {
|
|
391
|
-
const md = new Metadata();
|
|
392
|
-
const convoDetailEntityAI = await md.GetEntityObject('Conversation Details', user);
|
|
393
|
-
convoDetailEntityAI.NewRecord();
|
|
394
|
-
convoDetailEntityAI.HiddenToUser = false;
|
|
395
|
-
convoDetailEntityAI.ConversationID = conversationID;
|
|
396
|
-
const systemMessages = apiResponse.messages.filter((m) => m.role === 'system');
|
|
397
|
-
const lastSystemMessage = systemMessages[systemMessages.length - 1];
|
|
398
|
-
convoDetailEntityAI.Message = lastSystemMessage?.content;
|
|
399
|
-
convoDetailEntityAI.Role = 'AI';
|
|
400
|
-
if (await convoDetailEntityAI.Save()) {
|
|
401
|
-
return convoDetailEntityAI.ID;
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
LogError(`Error saving conversation detail entity for AI message: ${lastSystemMessage?.content}`, undefined, convoDetailEntityAI.LatestResult);
|
|
405
|
-
return '';
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
async buildBaseSkipRequest(contextUser, dataSource, includeEntities, includeQueries, includeNotes, filterUserNotesToContextUser, includeRequests, forceEntitiesRefresh = false, includeCallBackKeyAndAccessToken = false, additionalTokenInfo = {}) {
|
|
409
|
-
const skipConfigInfo = configInfo.askSkip;
|
|
410
|
-
const entities = includeEntities ? await this.BuildSkipEntities(dataSource, forceEntitiesRefresh) : [];
|
|
411
|
-
const queries = includeQueries ? this.BuildSkipQueries() : [];
|
|
412
|
-
const requests = includeRequests ? await this.BuildSkipRequests(contextUser) : [];
|
|
413
|
-
let accessToken;
|
|
414
|
-
if (includeCallBackKeyAndAccessToken) {
|
|
415
|
-
const tokenInfo = {
|
|
416
|
-
type: 'skip_api_request',
|
|
417
|
-
userEmail: contextUser.Email,
|
|
418
|
-
userName: contextUser.Name,
|
|
419
|
-
userID: contextUser.ID,
|
|
420
|
-
...additionalTokenInfo
|
|
421
|
-
};
|
|
422
|
-
accessToken = registerAccessToken(undefined, 1000 * 60 * 10, tokenInfo);
|
|
423
|
-
}
|
|
424
|
-
return {
|
|
425
|
-
entities,
|
|
426
|
-
queries,
|
|
427
|
-
notes: undefined,
|
|
428
|
-
noteTypes: undefined,
|
|
429
|
-
userEmail: contextUser.Email,
|
|
430
|
-
requests,
|
|
431
|
-
accessToken,
|
|
432
|
-
organizationID: skipConfigInfo.orgID,
|
|
433
|
-
organizationInfo: configInfo?.askSkip?.organizationInfo,
|
|
434
|
-
apiKeys: this.buildSkipAPIKeys(),
|
|
435
|
-
callingServerURL: accessToken ? (publicUrl || `${baseUrl}:${graphqlPort}${graphqlRootPath}`) : undefined,
|
|
436
|
-
callingServerAPIKey: accessToken ? callbackAPIKey : undefined,
|
|
437
|
-
callingServerAccessToken: accessToken ? accessToken.Token : undefined
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
async buildSkipLearningAPIRequest(learningCycleId, lastLearningCycleDate, includeEntities, includeQueries, includeNotes, includeRequests, dataSource, contextUser, forceEntitiesRefresh = false, includeCallBackKeyAndAccessToken = false) {
|
|
441
|
-
const baseRequest = await this.buildBaseSkipRequest(contextUser, dataSource, includeEntities, includeQueries, includeNotes, false, includeRequests, forceEntitiesRefresh, includeCallBackKeyAndAccessToken);
|
|
442
|
-
const newConversations = await this.BuildSkipLearningCycleNewConversations(lastLearningCycleDate, dataSource, contextUser);
|
|
443
|
-
const input = {
|
|
444
|
-
organizationId: baseRequest.organizationID,
|
|
445
|
-
organizationInfo: baseRequest.organizationInfo,
|
|
446
|
-
learningCycleId,
|
|
447
|
-
lastLearningCycleDate,
|
|
448
|
-
newConversations,
|
|
449
|
-
entities: baseRequest.entities,
|
|
450
|
-
queries: baseRequest.queries,
|
|
451
|
-
notes: baseRequest.notes,
|
|
452
|
-
noteTypes: baseRequest.noteTypes,
|
|
453
|
-
requests: baseRequest.requests,
|
|
454
|
-
apiKeys: baseRequest.apiKeys
|
|
455
|
-
};
|
|
456
|
-
return input;
|
|
457
|
-
}
|
|
458
|
-
async BuildSkipLearningCycleNewConversations(lastLearningCycleDate, dataSource, contextUser) {
|
|
459
|
-
try {
|
|
460
|
-
const rv = new RunView();
|
|
461
|
-
const conversationsSinceLastLearningCycle = await rv.RunView({
|
|
462
|
-
EntityName: 'Conversations',
|
|
463
|
-
ExtraFilter: `ID IN (SELECT ConversationID FROM __mj.vwConversationDetails WHERE __mj_UpdatedAt >= '${lastLearningCycleDate.toISOString()}')`,
|
|
464
|
-
ResultType: 'entity_object',
|
|
465
|
-
}, contextUser);
|
|
466
|
-
if (!conversationsSinceLastLearningCycle.Success || conversationsSinceLastLearningCycle.Results.length === 0) {
|
|
467
|
-
return [];
|
|
468
|
-
}
|
|
469
|
-
return await Promise.all(conversationsSinceLastLearningCycle.Results.map(async (c) => {
|
|
470
|
-
return {
|
|
471
|
-
id: c.ID,
|
|
472
|
-
name: c.Name,
|
|
473
|
-
userId: c.UserID,
|
|
474
|
-
user: c.User,
|
|
475
|
-
description: c.Description,
|
|
476
|
-
messages: await this.LoadConversationDetailsIntoSkipMessages(dataSource, c.ID),
|
|
477
|
-
createdAt: c.__mj_CreatedAt,
|
|
478
|
-
updatedAt: c.__mj_UpdatedAt
|
|
479
|
-
};
|
|
480
|
-
}));
|
|
481
|
-
}
|
|
482
|
-
catch (e) {
|
|
483
|
-
LogError(`Error loading conversations since last learning cycle: ${e}`);
|
|
484
|
-
return [];
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
async BuildSkipRequests(contextUser) {
|
|
488
|
-
try {
|
|
489
|
-
const md = new Metadata();
|
|
490
|
-
const requestEntity = await md.GetEntityObject('AI Agent Requests', contextUser);
|
|
491
|
-
const allRequests = await requestEntity.GetAll();
|
|
492
|
-
const requests = allRequests.map((r) => {
|
|
493
|
-
return {
|
|
494
|
-
id: r.ID,
|
|
495
|
-
agentId: r.AIAgentID,
|
|
496
|
-
agnet: r.AIAgent,
|
|
497
|
-
requestedAt: r.RequestedAt,
|
|
498
|
-
requestForUserId: r.RequestedForUserID,
|
|
499
|
-
requestForUser: r.RequestedForUser,
|
|
500
|
-
status: r.Status,
|
|
501
|
-
request: r.Request,
|
|
502
|
-
response: r.Response,
|
|
503
|
-
responseByUserId: r.ResponseByUserID,
|
|
504
|
-
responseByUser: r.ResponseByUser,
|
|
505
|
-
respondedAt: r.RespondedAt,
|
|
506
|
-
comments: r.Comments,
|
|
507
|
-
createdAt: r.__mj_CreatedAt,
|
|
508
|
-
updatedAt: r.__mj_UpdatedAt,
|
|
509
|
-
};
|
|
510
|
-
});
|
|
511
|
-
return requests;
|
|
512
|
-
}
|
|
513
|
-
catch (e) {
|
|
514
|
-
LogError(`Error loading requests: ${e}`);
|
|
515
|
-
return [];
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
async GetLastCompleteLearningCycleDate(agentID, user) {
|
|
519
|
-
const md = new Metadata();
|
|
520
|
-
const rv = new RunView();
|
|
521
|
-
const lastLearningCycleRV = await rv.RunView({
|
|
522
|
-
EntityName: 'AI Agent Learning Cycles',
|
|
523
|
-
ExtraFilter: `AgentID = '${agentID}' AND Status = 'Complete'`,
|
|
524
|
-
ResultType: 'entity_object',
|
|
525
|
-
OrderBy: 'StartedAt DESC',
|
|
526
|
-
MaxRows: 1,
|
|
527
|
-
}, user);
|
|
528
|
-
const lastLearningCycle = lastLearningCycleRV.Results[0];
|
|
529
|
-
if (lastLearningCycle) {
|
|
530
|
-
return lastLearningCycle.StartedAt;
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
return new Date(0);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
async buildSkipChatAPIRequest(messages, conversationId, dataContext, requestPhase, includeEntities, includeQueries, includeNotes, includeRequests, contextUser, dataSource, forceEntitiesRefresh = false, includeCallBackKeyAndAccessToken = false) {
|
|
537
|
-
const additionalTokenInfo = {
|
|
538
|
-
conversationId,
|
|
539
|
-
requestPhase,
|
|
540
|
-
};
|
|
541
|
-
const baseRequest = await this.buildBaseSkipRequest(contextUser, dataSource, includeEntities, includeQueries, includeNotes, true, includeRequests, forceEntitiesRefresh, includeCallBackKeyAndAccessToken, additionalTokenInfo);
|
|
542
|
-
const artifacts = await this.buildSkipAPIArtifacts(contextUser, dataSource, conversationId);
|
|
543
|
-
const input = {
|
|
544
|
-
...baseRequest,
|
|
545
|
-
messages,
|
|
546
|
-
conversationID: conversationId.toString(),
|
|
547
|
-
dataContext: CopyScalarsAndArrays(dataContext),
|
|
548
|
-
requestPhase,
|
|
549
|
-
artifacts: artifacts
|
|
550
|
-
};
|
|
551
|
-
return input;
|
|
552
|
-
}
|
|
553
|
-
async buildSkipAPIArtifacts(contextUser, dataSource, conversationId) {
|
|
554
|
-
const md = new Metadata();
|
|
555
|
-
const ei = md.EntityByName('MJ: Conversation Artifacts');
|
|
556
|
-
const rv = new RunView();
|
|
557
|
-
const results = await rv.RunViews([
|
|
558
|
-
{
|
|
559
|
-
EntityName: "MJ: Conversation Artifacts",
|
|
560
|
-
ExtraFilter: `ConversationID='${conversationId}'`,
|
|
561
|
-
OrderBy: "__mj_CreatedAt"
|
|
562
|
-
},
|
|
563
|
-
{
|
|
564
|
-
EntityName: "MJ: Artifact Types",
|
|
565
|
-
OrderBy: "Name"
|
|
566
|
-
},
|
|
567
|
-
{
|
|
568
|
-
EntityName: "MJ: Conversation Artifact Versions",
|
|
569
|
-
ExtraFilter: `ConversationArtifactID IN (SELECT ID FROM [${ei.SchemaName}].[${ei.BaseView}] WHERE ConversationID='${conversationId}')`,
|
|
570
|
-
OrderBy: 'ConversationArtifactID, __mj_CreatedAt'
|
|
571
|
-
}
|
|
572
|
-
], contextUser);
|
|
573
|
-
if (results && results.length > 0 && results.every((r) => r.Success)) {
|
|
574
|
-
const types = results[1].Results.map((a) => {
|
|
575
|
-
const retVal = {
|
|
576
|
-
id: a.ID,
|
|
577
|
-
name: a.Name,
|
|
578
|
-
description: a.Description,
|
|
579
|
-
contentType: a.ContentType,
|
|
580
|
-
enabled: a.IsEnabled,
|
|
581
|
-
createdAt: a.__mj_CreatedAt,
|
|
582
|
-
updatedAt: a.__mj_UpdatedAt
|
|
583
|
-
};
|
|
584
|
-
return retVal;
|
|
585
|
-
});
|
|
586
|
-
const allConvoArtifacts = results[0].Results.map((a) => {
|
|
587
|
-
const rawVersions = results[2].Results;
|
|
588
|
-
const thisArtifactsVersions = rawVersions.filter(rv => rv.ConversationArtifactID === a.ID);
|
|
589
|
-
const versionsForThisArtifact = thisArtifactsVersions.map((v) => {
|
|
590
|
-
const versionRetVal = {
|
|
591
|
-
id: v.ID,
|
|
592
|
-
artifactId: v.ConversationArtifactID,
|
|
593
|
-
version: v.Version,
|
|
594
|
-
configuration: v.Configuration,
|
|
595
|
-
content: v.Content,
|
|
596
|
-
comments: v.Comments,
|
|
597
|
-
createdAt: v.__mj_CreatedAt,
|
|
598
|
-
updatedAt: v.__mj_UpdatedAt
|
|
599
|
-
};
|
|
600
|
-
return versionRetVal;
|
|
601
|
-
});
|
|
602
|
-
const artifactRetVal = {
|
|
603
|
-
id: a.ID,
|
|
604
|
-
name: a.Name,
|
|
605
|
-
description: a.Description,
|
|
606
|
-
comments: a.Comments,
|
|
607
|
-
sharingScope: a.SharingScope,
|
|
608
|
-
versions: versionsForThisArtifact,
|
|
609
|
-
conversationId: a.ConversationID,
|
|
610
|
-
artifactType: types.find((t => t.id === a.ArtifactTypeID)),
|
|
611
|
-
createdAt: a.__mj_CreatedAt,
|
|
612
|
-
updatedAt: a.__mj_UpdatedAt
|
|
613
|
-
};
|
|
614
|
-
return artifactRetVal;
|
|
615
|
-
});
|
|
616
|
-
return allConvoArtifacts;
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
return [];
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
async ExecuteAskSkipRunScript({ dataSource, userPayload }, pubSub, DataContextId, ScriptText) {
|
|
623
|
-
const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
|
|
624
|
-
if (!user)
|
|
625
|
-
throw new Error(`User ${userPayload.email} not found in UserCache`);
|
|
626
|
-
const dataContext = new DataContext();
|
|
627
|
-
await dataContext.Load(DataContextId, dataSource, true, false, 0, user);
|
|
628
|
-
const input = await this.buildSkipChatAPIRequest([], '', dataContext, 'run_existing_script', false, false, false, false, user, dataSource, false, false);
|
|
629
|
-
input.scriptText = ScriptText;
|
|
630
|
-
return this.handleSimpleSkipChatPostRequest(input, undefined, undefined, undefined, userPayload.userRecord, userPayload);
|
|
631
|
-
}
|
|
632
|
-
buildSkipAPIKeys() {
|
|
633
|
-
return [
|
|
634
|
-
{
|
|
635
|
-
vendorDriverName: 'OpenAILLM',
|
|
636
|
-
apiKey: GetAIAPIKey('OpenAILLM'),
|
|
637
|
-
},
|
|
638
|
-
{
|
|
639
|
-
vendorDriverName: 'AnthropicLLM',
|
|
640
|
-
apiKey: GetAIAPIKey('AnthropicLLM'),
|
|
641
|
-
},
|
|
642
|
-
{
|
|
643
|
-
vendorDriverName: 'GeminiLLM',
|
|
644
|
-
apiKey: GetAIAPIKey('GeminiLLM'),
|
|
645
|
-
},
|
|
646
|
-
{
|
|
647
|
-
vendorDriverName: 'GroqLLM',
|
|
648
|
-
apiKey: GetAIAPIKey('GroqLLM'),
|
|
649
|
-
},
|
|
650
|
-
{
|
|
651
|
-
vendorDriverName: 'MistralLLM',
|
|
652
|
-
apiKey: GetAIAPIKey('MistralLLM'),
|
|
653
|
-
},
|
|
654
|
-
{
|
|
655
|
-
vendorDriverName: 'CerebrasLLM',
|
|
656
|
-
apiKey: GetAIAPIKey('CerebrasLLM'),
|
|
657
|
-
},
|
|
658
|
-
];
|
|
659
|
-
}
|
|
660
|
-
async ReattachToProcessingConversation(ConversationId, { userPayload, providers }, pubSub) {
|
|
661
|
-
try {
|
|
662
|
-
const md = GetReadWriteProvider(providers);
|
|
663
|
-
const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
|
|
664
|
-
if (!user) {
|
|
665
|
-
LogError(`User ${userPayload.email} not found in UserCache`);
|
|
666
|
-
return null;
|
|
667
|
-
}
|
|
668
|
-
const convoEntity = await md.GetEntityObject('Conversations', user);
|
|
669
|
-
const loadResult = await convoEntity.Load(ConversationId);
|
|
670
|
-
if (!loadResult) {
|
|
671
|
-
LogError(`Could not load conversation ${ConversationId} for re-attachment`);
|
|
672
|
-
return null;
|
|
673
|
-
}
|
|
674
|
-
if (convoEntity.UserID !== user.ID) {
|
|
675
|
-
LogError(`Conversation ${ConversationId} does not belong to user ${user.Email}`);
|
|
676
|
-
return null;
|
|
677
|
-
}
|
|
678
|
-
if (convoEntity.Status === 'Processing') {
|
|
679
|
-
activeStreams.addSession(ConversationId, userPayload.sessionId);
|
|
680
|
-
const lastStatusMessage = activeStreams.getStatus(ConversationId) || 'Processing...';
|
|
681
|
-
const startTime = activeStreams.getStartTime(ConversationId);
|
|
682
|
-
const isStreamActive = activeStreams.isActive(ConversationId);
|
|
683
|
-
if (isStreamActive) {
|
|
684
|
-
const statusMessage = {
|
|
685
|
-
type: 'AskSkip',
|
|
686
|
-
status: 'OK',
|
|
687
|
-
ResponsePhase: 'Processing',
|
|
688
|
-
conversationID: convoEntity.ID,
|
|
689
|
-
message: lastStatusMessage,
|
|
690
|
-
};
|
|
691
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
692
|
-
pushStatusUpdates: {
|
|
693
|
-
message: JSON.stringify(statusMessage),
|
|
694
|
-
sessionId: userPayload.sessionId
|
|
695
|
-
}
|
|
696
|
-
});
|
|
697
|
-
LogStatus(`Re-attached session ${userPayload.sessionId} to active stream for conversation ${ConversationId}, last status: ${lastStatusMessage}`);
|
|
698
|
-
return {
|
|
699
|
-
lastStatusMessage,
|
|
700
|
-
startTime: startTime || convoEntity.__mj_UpdatedAt
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
else {
|
|
704
|
-
const statusMessage = {
|
|
705
|
-
type: 'AskSkip',
|
|
706
|
-
status: 'OK',
|
|
707
|
-
ResponsePhase: 'Processing',
|
|
708
|
-
conversationID: convoEntity.ID,
|
|
709
|
-
message: 'Processing...',
|
|
710
|
-
};
|
|
711
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
712
|
-
pushStatusUpdates: {
|
|
713
|
-
message: JSON.stringify(statusMessage),
|
|
714
|
-
sessionId: userPayload.sessionId
|
|
715
|
-
}
|
|
716
|
-
});
|
|
717
|
-
LogStatus(`Re-attached session ${userPayload.sessionId} to conversation ${ConversationId}, but stream is inactive`);
|
|
718
|
-
return {
|
|
719
|
-
lastStatusMessage: 'Processing...',
|
|
720
|
-
startTime: convoEntity.__mj_UpdatedAt
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
else {
|
|
725
|
-
LogStatus(`Conversation ${ConversationId} is not processing (Status: ${convoEntity.Status})`);
|
|
726
|
-
return null;
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
catch (error) {
|
|
730
|
-
LogError(`Error re-attaching to conversation: ${error}`);
|
|
731
|
-
return null;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
async ExecuteAskSkipAnalysisQuery(UserQuestion, ConversationId, { dataSource, userPayload, providers }, pubSub, DataContextId, ForceEntityRefresh, StartTime) {
|
|
735
|
-
const md = GetReadWriteProvider(providers);
|
|
736
|
-
const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
|
|
737
|
-
if (!user)
|
|
738
|
-
throw new Error(`User ${userPayload.email} not found in UserCache`);
|
|
739
|
-
const requestStartTime = StartTime || new Date();
|
|
740
|
-
const { convoEntity, dataContextEntity, convoDetailEntity, dataContext } = await this.HandleSkipChatInitialObjectLoading(dataSource, ConversationId, UserQuestion, user, userPayload, md, DataContextId);
|
|
741
|
-
await this.setConversationStatus(convoEntity, 'Processing', userPayload, pubSub);
|
|
742
|
-
const messages = await this.LoadConversationDetailsIntoSkipMessages(dataSource, convoEntity.ID, AskSkipResolver_1._maxHistoricalMessages);
|
|
743
|
-
const conversationDetailCount = 1;
|
|
744
|
-
const input = await this.buildSkipChatAPIRequest(messages, ConversationId, dataContext, 'initial_request', true, true, true, false, user, dataSource, ForceEntityRefresh === undefined ? false : ForceEntityRefresh, true);
|
|
745
|
-
return this.HandleSkipChatRequest(input, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, md, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, requestStartTime);
|
|
746
|
-
}
|
|
747
|
-
buildQueryCategoryPath(md, categoryID) {
|
|
748
|
-
const cat = md.QueryCategories.find((c) => c.ID === categoryID);
|
|
749
|
-
if (!cat)
|
|
750
|
-
return '';
|
|
751
|
-
if (!cat.ParentID)
|
|
752
|
-
return cat.Name;
|
|
753
|
-
const parentPath = this.buildQueryCategoryPath(md, cat.ParentID);
|
|
754
|
-
return parentPath ? `${parentPath}/${cat.Name}` : cat.Name;
|
|
755
|
-
}
|
|
756
|
-
BuildSkipQueries(status = 'Approved') {
|
|
757
|
-
const md = new Metadata();
|
|
758
|
-
const approvedQueries = md.Queries.filter((q) => q.Status === status);
|
|
759
|
-
return approvedQueries.map((q) => ({
|
|
760
|
-
ID: q.ID,
|
|
761
|
-
Name: q.Name,
|
|
762
|
-
Description: q.Description,
|
|
763
|
-
Category: q.Category,
|
|
764
|
-
CategoryPath: this.buildQueryCategoryPath(md, q.CategoryID),
|
|
765
|
-
CategoryID: q.CategoryID,
|
|
766
|
-
SQL: q.SQL,
|
|
767
|
-
Status: q.Status,
|
|
768
|
-
QualityRank: q.QualityRank,
|
|
769
|
-
EmbeddingVector: q.EmbeddingVector,
|
|
770
|
-
EmbeddingModelID: q.EmbeddingModelID,
|
|
771
|
-
EmbeddingModelName: q.EmbeddingModel,
|
|
772
|
-
Fields: q.Fields.map((f) => ({
|
|
773
|
-
ID: f.ID,
|
|
774
|
-
QueryID: f.QueryID,
|
|
775
|
-
Name: f.Name,
|
|
776
|
-
Description: f.Description,
|
|
777
|
-
Sequence: f.Sequence,
|
|
778
|
-
SQLBaseType: f.SQLBaseType,
|
|
779
|
-
SQLFullType: f.SQLFullType,
|
|
780
|
-
SourceEntityID: f.SourceEntityID,
|
|
781
|
-
SourceEntity: f.SourceEntity,
|
|
782
|
-
SourceFieldName: f.SourceFieldName,
|
|
783
|
-
IsComputed: f.IsComputed,
|
|
784
|
-
ComputationDescription: f.ComputationDescription,
|
|
785
|
-
IsSummary: f.IsSummary,
|
|
786
|
-
SummaryDescription: f.SummaryDescription
|
|
787
|
-
})),
|
|
788
|
-
Parameters: q.Parameters.map((p) => ({
|
|
789
|
-
ID: p.ID,
|
|
790
|
-
QueryID: p.QueryID,
|
|
791
|
-
Name: p.Name,
|
|
792
|
-
Description: p.Description,
|
|
793
|
-
Type: p.Type,
|
|
794
|
-
IsRequired: p.IsRequired,
|
|
795
|
-
DefaultValue: p.DefaultValue,
|
|
796
|
-
SampleValue: p.SampleValue,
|
|
797
|
-
ValidationFilters: p.ValidationFilters
|
|
798
|
-
})),
|
|
799
|
-
Entities: q.Entities.map((e) => ({
|
|
800
|
-
ID: e.ID,
|
|
801
|
-
QueryID: e.QueryID,
|
|
802
|
-
EntityID: e.EntityID,
|
|
803
|
-
Entity: e.Entity
|
|
804
|
-
})),
|
|
805
|
-
CacheEnabled: q.CacheEnabled,
|
|
806
|
-
CacheMaxSize: q.CacheMaxSize,
|
|
807
|
-
CacheTTLMinutes: q.CacheMaxSize,
|
|
808
|
-
CacheValidationSQL: q.CacheValidationSQL
|
|
809
|
-
}));
|
|
810
|
-
}
|
|
811
|
-
async PackEntityRows(e, dataSource) {
|
|
812
|
-
try {
|
|
813
|
-
if (e.RowsToPackWithSchema === 'None')
|
|
814
|
-
return [];
|
|
815
|
-
const fields = e.Fields.filter((f) => {
|
|
816
|
-
const scopes = f.ScopeDefault?.split(',').map((s) => s.trim().toLowerCase());
|
|
817
|
-
return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai');
|
|
818
|
-
}).map(f => `[${f.Name}]`).join(',');
|
|
819
|
-
let sql = '';
|
|
820
|
-
switch (e.RowsToPackWithSchema) {
|
|
821
|
-
case 'All':
|
|
822
|
-
sql = `SELECT ${fields} FROM ${e.SchemaName}.${e.BaseView}`;
|
|
823
|
-
break;
|
|
824
|
-
case 'Sample':
|
|
825
|
-
switch (e.RowsToPackSampleMethod) {
|
|
826
|
-
case 'random':
|
|
827
|
-
sql = `SELECT TOP ${e.RowsToPackSampleCount} ${fields} FROM [${e.SchemaName}].[${e.BaseView}] ORDER BY newid()`;
|
|
828
|
-
break;
|
|
829
|
-
case 'top n':
|
|
830
|
-
const orderBy = e.RowsToPackSampleOrder ? ` ORDER BY [${e.RowsToPackSampleOrder}]` : '';
|
|
831
|
-
sql = `SELECT TOP ${e.RowsToPackSampleCount} ${fields} FROM [${e.SchemaName}].[${e.BaseView}]${orderBy}`;
|
|
832
|
-
break;
|
|
833
|
-
case 'bottom n':
|
|
834
|
-
const firstPrimaryKey = e.FirstPrimaryKey.Name;
|
|
835
|
-
const innerOrderBy = e.RowsToPackSampleOrder ? `[${e.RowsToPackSampleOrder}]` : `[${firstPrimaryKey}] DESC`;
|
|
836
|
-
sql = `SELECT * FROM (
|
|
837
|
-
SELECT TOP ${e.RowsToPackSampleCount} ${fields}
|
|
838
|
-
FROM [${e.SchemaName}].[${e.BaseView}]
|
|
839
|
-
ORDER BY ${innerOrderBy}
|
|
840
|
-
) sub
|
|
841
|
-
ORDER BY [${firstPrimaryKey}] ASC;`;
|
|
842
|
-
break;
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
const request = new mssql.Request(dataSource);
|
|
846
|
-
const result = await request.query(sql);
|
|
847
|
-
if (!result || !result.recordset) {
|
|
848
|
-
return [];
|
|
849
|
-
}
|
|
850
|
-
else {
|
|
851
|
-
return result.recordset;
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
catch (e) {
|
|
855
|
-
LogError(`AskSkipResolver::PackEntityRows: ${e}`);
|
|
856
|
-
return [];
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
async PackFieldPossibleValues(f, dataSource) {
|
|
860
|
-
try {
|
|
861
|
-
if (f.ValuesToPackWithSchema === 'None') {
|
|
862
|
-
return [];
|
|
863
|
-
}
|
|
864
|
-
else if (f.ValuesToPackWithSchema === 'All') {
|
|
865
|
-
return await this.GetFieldDistinctValues(f, dataSource);
|
|
866
|
-
}
|
|
867
|
-
else if (f.ValuesToPackWithSchema === 'Auto') {
|
|
868
|
-
if (f.ValueListTypeEnum === 'List') {
|
|
869
|
-
return f.EntityFieldValues.map((v) => {
|
|
870
|
-
return { value: v.Value, displayValue: v.Value };
|
|
871
|
-
});
|
|
872
|
-
}
|
|
873
|
-
else if (f.ValueListTypeEnum === 'ListOrUserEntry') {
|
|
874
|
-
const values = await this.GetFieldDistinctValues(f, dataSource);
|
|
875
|
-
if (!values || values.length === 0) {
|
|
876
|
-
return f.EntityFieldValues.map((v) => {
|
|
877
|
-
return { value: v.Value, displayValue: v.Value };
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
else {
|
|
881
|
-
return [...new Set([...f.EntityFieldValues.map((v) => {
|
|
882
|
-
return { value: v.Value, displayValue: v.Value };
|
|
883
|
-
}), ...values])];
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
return [];
|
|
888
|
-
}
|
|
889
|
-
catch (e) {
|
|
890
|
-
LogError(`AskSkipResolver::PackFieldPossibleValues: ${e}`);
|
|
891
|
-
return [];
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
async GetFieldDistinctValues(f, dataSource) {
|
|
895
|
-
try {
|
|
896
|
-
const sql = `SELECT DISTINCT ${f.Name} FROM ${f.SchemaName}.${f.BaseView}`;
|
|
897
|
-
const request = new mssql.Request(dataSource);
|
|
898
|
-
const result = await request.query(sql);
|
|
899
|
-
if (!result || !result.recordset) {
|
|
900
|
-
return [];
|
|
901
|
-
}
|
|
902
|
-
else {
|
|
903
|
-
return result.recordset.map((r) => {
|
|
904
|
-
return {
|
|
905
|
-
value: r[f.Name],
|
|
906
|
-
displayValue: r[f.Name]
|
|
907
|
-
};
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
catch (e) {
|
|
912
|
-
LogError(`AskSkipResolver::GetFieldDistinctValues: ${e}`);
|
|
913
|
-
return [];
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
static __skipEntitiesCache$ = new BehaviorSubject(null);
|
|
917
|
-
static __lastRefreshTime = 0;
|
|
918
|
-
static __refreshInProgress = null;
|
|
919
|
-
async refreshSkipEntities(dataSource) {
|
|
920
|
-
try {
|
|
921
|
-
const md = new Metadata();
|
|
922
|
-
console.log(`[refreshSkipEntities] Total entities in metadata: ${md.Entities.length}`);
|
|
923
|
-
console.log(`[refreshSkipEntities] Config excludeSchemas: ${JSON.stringify(configInfo.askSkip?.entitiesToSend?.excludeSchemas)}`);
|
|
924
|
-
console.log(`[refreshSkipEntities] Config includeEntitiesFromExcludedSchemas: ${JSON.stringify(configInfo.askSkip?.entitiesToSend?.includeEntitiesFromExcludedSchemas)}`);
|
|
925
|
-
const skipSpecialIncludeEntities = (configInfo.askSkip?.entitiesToSend?.includeEntitiesFromExcludedSchemas ?? [])
|
|
926
|
-
.map((e) => e.trim().toLowerCase());
|
|
927
|
-
const entities = md.Entities.filter((e) => {
|
|
928
|
-
if (!configInfo.askSkip.entitiesToSend.excludeSchemas.includes(e.SchemaName) ||
|
|
929
|
-
skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase())) {
|
|
930
|
-
const sd = e.ScopeDefault?.trim();
|
|
931
|
-
if (sd && sd.length > 0) {
|
|
932
|
-
const scopes = sd.split(',').map((s) => s.trim().toLowerCase()) ?? ['all'];
|
|
933
|
-
return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai') || skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase());
|
|
934
|
-
}
|
|
935
|
-
else {
|
|
936
|
-
return true;
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
return false;
|
|
940
|
-
});
|
|
941
|
-
console.log(`[refreshSkipEntities] Filtered entities count: ${entities.length}`);
|
|
942
|
-
if (entities.length === 0) {
|
|
943
|
-
console.warn(`[refreshSkipEntities] WARNING: No entities passed filtering! This will result in empty Skip entities list.`);
|
|
944
|
-
}
|
|
945
|
-
const result = await Promise.all(entities.map((e) => this.PackSingleSkipEntityInfo(e, dataSource)));
|
|
946
|
-
console.log(`[refreshSkipEntities] Successfully packed ${result.length} entities for Skip`);
|
|
947
|
-
AskSkipResolver_1.__lastRefreshTime = Date.now();
|
|
948
|
-
return result;
|
|
949
|
-
}
|
|
950
|
-
catch (e) {
|
|
951
|
-
LogError(`AskSkipResolver::refreshSkipEntities: ${e}`);
|
|
952
|
-
return [];
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
async BuildSkipEntities(dataSource, forceRefresh = false, refreshIntervalMinutes = 15) {
|
|
956
|
-
try {
|
|
957
|
-
const now = Date.now();
|
|
958
|
-
const cacheExpired = (now - AskSkipResolver_1.__lastRefreshTime) > (refreshIntervalMinutes * 60 * 1000);
|
|
959
|
-
const cacheIsEmpty = AskSkipResolver_1.__skipEntitiesCache$.value === null;
|
|
960
|
-
console.log(`[BuildSkipEntities] forceRefresh: ${forceRefresh}, cacheExpired: ${cacheExpired}, cacheIsEmpty: ${cacheIsEmpty}`);
|
|
961
|
-
if (forceRefresh || cacheExpired || cacheIsEmpty) {
|
|
962
|
-
if (AskSkipResolver_1.__refreshInProgress) {
|
|
963
|
-
console.log(`[BuildSkipEntities] Refresh already in progress, waiting for it to complete...`);
|
|
964
|
-
return await AskSkipResolver_1.__refreshInProgress;
|
|
965
|
-
}
|
|
966
|
-
console.log(`[BuildSkipEntities] Starting new refresh operation...`);
|
|
967
|
-
AskSkipResolver_1.__refreshInProgress = this.refreshSkipEntities(dataSource);
|
|
968
|
-
try {
|
|
969
|
-
const newData = await AskSkipResolver_1.__refreshInProgress;
|
|
970
|
-
AskSkipResolver_1.__skipEntitiesCache$.next(newData);
|
|
971
|
-
console.log(`[BuildSkipEntities] Refresh complete, cached ${newData.length} entities`);
|
|
972
|
-
return newData;
|
|
973
|
-
}
|
|
974
|
-
finally {
|
|
975
|
-
AskSkipResolver_1.__refreshInProgress = null;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
const result = AskSkipResolver_1.__skipEntitiesCache$.value || [];
|
|
979
|
-
console.log(`[BuildSkipEntities] Returning ${result.length} entities from cache`);
|
|
980
|
-
return result;
|
|
981
|
-
}
|
|
982
|
-
catch (e) {
|
|
983
|
-
LogError(`AskSkipResolver::BuildSkipEntities: ${e}`);
|
|
984
|
-
return [];
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
async PackSingleSkipEntityInfo(e, dataSource) {
|
|
988
|
-
try {
|
|
989
|
-
const ret = {
|
|
990
|
-
id: e.ID,
|
|
991
|
-
name: e.Name,
|
|
992
|
-
schemaName: e.SchemaName,
|
|
993
|
-
baseView: e.BaseView,
|
|
994
|
-
description: e.Description,
|
|
995
|
-
fields: await Promise.all(e.Fields.filter(f => {
|
|
996
|
-
const scopes = f.ScopeDefault?.split(',').map((s) => s.trim().toLowerCase());
|
|
997
|
-
return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai');
|
|
998
|
-
}).map(f => {
|
|
999
|
-
return this.PackSingleSkipEntityField(f, dataSource);
|
|
1000
|
-
})),
|
|
1001
|
-
relatedEntities: e.RelatedEntities.map((r) => {
|
|
1002
|
-
return this.PackSingleSkipEntityRelationship(r);
|
|
1003
|
-
}),
|
|
1004
|
-
rowsPacked: e.RowsToPackWithSchema,
|
|
1005
|
-
rowsSampleMethod: e.RowsToPackSampleMethod,
|
|
1006
|
-
rows: await this.PackEntityRows(e, dataSource)
|
|
1007
|
-
};
|
|
1008
|
-
return ret;
|
|
1009
|
-
}
|
|
1010
|
-
catch (e) {
|
|
1011
|
-
LogError(`AskSkipResolver::PackSingleSkipEntityInfo: ${e}`);
|
|
1012
|
-
return null;
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
PackSingleSkipEntityRelationship(r) {
|
|
1016
|
-
try {
|
|
1017
|
-
return {
|
|
1018
|
-
entityID: r.EntityID,
|
|
1019
|
-
relatedEntityID: r.RelatedEntityID,
|
|
1020
|
-
type: r.Type,
|
|
1021
|
-
entityKeyField: r.EntityKeyField,
|
|
1022
|
-
relatedEntityJoinField: r.RelatedEntityJoinField,
|
|
1023
|
-
joinView: r.JoinView,
|
|
1024
|
-
joinEntityJoinField: r.JoinEntityJoinField,
|
|
1025
|
-
joinEntityInverseJoinField: r.JoinEntityInverseJoinField,
|
|
1026
|
-
entity: r.Entity,
|
|
1027
|
-
entityBaseView: r.EntityBaseView,
|
|
1028
|
-
relatedEntity: r.RelatedEntity,
|
|
1029
|
-
relatedEntityBaseView: r.RelatedEntityBaseView,
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
catch (e) {
|
|
1033
|
-
LogError(`AskSkipResolver::PackSingleSkipEntityRelationship: ${e}`);
|
|
1034
|
-
return null;
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
async PackSingleSkipEntityField(f, dataSource) {
|
|
1038
|
-
try {
|
|
1039
|
-
return {
|
|
1040
|
-
entityID: f.EntityID,
|
|
1041
|
-
sequence: f.Sequence,
|
|
1042
|
-
name: f.Name,
|
|
1043
|
-
displayName: f.DisplayName,
|
|
1044
|
-
category: f.Category,
|
|
1045
|
-
type: f.Type,
|
|
1046
|
-
description: f.Description,
|
|
1047
|
-
isPrimaryKey: f.IsPrimaryKey,
|
|
1048
|
-
allowsNull: f.AllowsNull,
|
|
1049
|
-
isUnique: f.IsUnique,
|
|
1050
|
-
length: f.Length,
|
|
1051
|
-
precision: f.Precision,
|
|
1052
|
-
scale: f.Scale,
|
|
1053
|
-
sqlFullType: f.SQLFullType,
|
|
1054
|
-
defaultValue: f.DefaultValue,
|
|
1055
|
-
autoIncrement: f.AutoIncrement,
|
|
1056
|
-
valueListType: f.ValueListType,
|
|
1057
|
-
extendedType: f.ExtendedType,
|
|
1058
|
-
defaultInView: f.DefaultInView,
|
|
1059
|
-
defaultColumnWidth: f.DefaultColumnWidth,
|
|
1060
|
-
isVirtual: f.IsVirtual,
|
|
1061
|
-
isNameField: f.IsNameField,
|
|
1062
|
-
relatedEntityID: f.RelatedEntityID,
|
|
1063
|
-
relatedEntityFieldName: f.RelatedEntityFieldName,
|
|
1064
|
-
relatedEntity: f.RelatedEntity,
|
|
1065
|
-
relatedEntitySchemaName: f.RelatedEntitySchemaName,
|
|
1066
|
-
relatedEntityBaseView: f.RelatedEntityBaseView,
|
|
1067
|
-
possibleValues: await this.PackFieldPossibleValues(f, dataSource),
|
|
1068
|
-
};
|
|
1069
|
-
}
|
|
1070
|
-
catch (e) {
|
|
1071
|
-
LogError(`AskSkipResolver::PackSingleSkipEntityField: ${e}`);
|
|
1072
|
-
return null;
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
async HandleSkipChatInitialObjectLoading(dataSource, ConversationId, UserQuestion, user, userPayload, md, DataContextId) {
|
|
1076
|
-
const convoEntity = await md.GetEntityObject('Conversations', user);
|
|
1077
|
-
let dataContextEntity;
|
|
1078
|
-
if (!ConversationId || ConversationId.length === 0) {
|
|
1079
|
-
convoEntity.NewRecord();
|
|
1080
|
-
if (user) {
|
|
1081
|
-
convoEntity.UserID = user.ID;
|
|
1082
|
-
convoEntity.Name = AskSkipResolver_1._defaultNewChatName;
|
|
1083
|
-
convoEntity.Status = 'Available';
|
|
1084
|
-
dataContextEntity = await md.GetEntityObject('Data Contexts', user);
|
|
1085
|
-
if (!DataContextId || DataContextId.length === 0) {
|
|
1086
|
-
dataContextEntity.NewRecord();
|
|
1087
|
-
dataContextEntity.UserID = user.ID;
|
|
1088
|
-
dataContextEntity.Name = 'Data Context for Skip Conversation ';
|
|
1089
|
-
if (!(await dataContextEntity.Save())) {
|
|
1090
|
-
LogError(`Creating a new data context failed`, undefined, dataContextEntity.LatestResult);
|
|
1091
|
-
throw new Error(`Creating a new data context failed`);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
else {
|
|
1095
|
-
const dcLoadResult = await dataContextEntity.Load(DataContextId);
|
|
1096
|
-
if (!dcLoadResult) {
|
|
1097
|
-
throw new Error(`Loading DataContextEntity for DataContextId ${DataContextId} failed`);
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
convoEntity.DataContextID = dataContextEntity.ID;
|
|
1101
|
-
if (await convoEntity.Save()) {
|
|
1102
|
-
ConversationId = convoEntity.ID;
|
|
1103
|
-
if (!DataContextId || dataContextEntity.ID.length === 0) {
|
|
1104
|
-
dataContextEntity.Name += ` ${ConversationId}`;
|
|
1105
|
-
const dciSaveResult = await dataContextEntity.Save();
|
|
1106
|
-
if (!dciSaveResult) {
|
|
1107
|
-
LogError(`Error saving DataContextEntity for conversation: ${ConversationId}`, undefined, dataContextEntity.LatestResult);
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
else {
|
|
1112
|
-
LogError(`Creating a new conversation failed`, undefined, convoEntity.LatestResult);
|
|
1113
|
-
throw new Error(`Creating a new conversation failed`);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
else {
|
|
1117
|
-
throw new Error(`User ${userPayload.email} not found in UserCache`);
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
else {
|
|
1121
|
-
await convoEntity.Load(ConversationId);
|
|
1122
|
-
dataContextEntity = await md.GetEntityObject('Data Contexts', user);
|
|
1123
|
-
if (DataContextId && DataContextId.length > 0 && DataContextId !== convoEntity.DataContextID) {
|
|
1124
|
-
if (convoEntity.DataContextID === null) {
|
|
1125
|
-
convoEntity.DataContextID = DataContextId;
|
|
1126
|
-
const convoEntitySaveResult = await convoEntity.Save();
|
|
1127
|
-
if (!convoEntitySaveResult) {
|
|
1128
|
-
LogError(`Error saving conversation entity for conversation: ${ConversationId}`, undefined, convoEntity.LatestResult);
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
else {
|
|
1132
|
-
console.warn(`AskSkipResolver: DataContextId ${DataContextId} was passed in but it was ignored because it was different than the DataContextID in the conversation ${convoEntity.DataContextID}`);
|
|
1133
|
-
}
|
|
1134
|
-
if (convoEntity.DataContextID)
|
|
1135
|
-
await dataContextEntity.Load(convoEntity.DataContextID);
|
|
1136
|
-
}
|
|
1137
|
-
else if ((!DataContextId || DataContextId.length === 0) && (!convoEntity.DataContextID || convoEntity.DataContextID.length === 0)) {
|
|
1138
|
-
dataContextEntity.NewRecord();
|
|
1139
|
-
dataContextEntity.UserID = user.ID;
|
|
1140
|
-
dataContextEntity.Name = 'Data Context for Skip Conversation ' + ConversationId;
|
|
1141
|
-
if (await dataContextEntity.Save()) {
|
|
1142
|
-
DataContextId = convoEntity.DataContextID;
|
|
1143
|
-
convoEntity.DataContextID = dataContextEntity.ID;
|
|
1144
|
-
if (!await convoEntity.Save()) {
|
|
1145
|
-
LogError(`Error saving conversation entity for conversation: ${ConversationId}`, undefined, convoEntity.LatestResult);
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
else
|
|
1149
|
-
LogError(`Error saving DataContextEntity for conversation: ${ConversationId}`, undefined, dataContextEntity.LatestResult);
|
|
1150
|
-
}
|
|
1151
|
-
else {
|
|
1152
|
-
await dataContextEntity.Load(convoEntity.DataContextID);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
const convoDetailEntity = await md.GetEntityObject('Conversation Details', user);
|
|
1156
|
-
convoDetailEntity.NewRecord();
|
|
1157
|
-
convoDetailEntity.ConversationID = ConversationId;
|
|
1158
|
-
convoDetailEntity.UserID = user.ID;
|
|
1159
|
-
convoDetailEntity.Message = UserQuestion;
|
|
1160
|
-
convoDetailEntity.Role = 'User';
|
|
1161
|
-
convoDetailEntity.HiddenToUser = false;
|
|
1162
|
-
let convoDetailSaveResult = await convoDetailEntity.Save();
|
|
1163
|
-
if (!convoDetailSaveResult) {
|
|
1164
|
-
LogError(`Error saving conversation detail entity for user message: ${UserQuestion}`, undefined, convoDetailEntity.LatestResult);
|
|
1165
|
-
}
|
|
1166
|
-
const dataContext = MJGlobal.Instance.ClassFactory.CreateInstance(DataContext);
|
|
1167
|
-
await dataContext.Load(dataContextEntity.ID, dataSource, false, false, 0, user);
|
|
1168
|
-
return { dataContext, convoEntity, dataContextEntity, convoDetailEntity };
|
|
1169
|
-
}
|
|
1170
|
-
async LoadConversationDetailsIntoSkipMessages(dataSource, ConversationId, maxHistoricalMessages, roleFilter) {
|
|
1171
|
-
try {
|
|
1172
|
-
if (!ConversationId || ConversationId.length === 0) {
|
|
1173
|
-
throw new Error(`ConversationId is required`);
|
|
1174
|
-
}
|
|
1175
|
-
const md = new Metadata();
|
|
1176
|
-
const e = md.Entities.find((e) => e.Name === 'Conversation Details');
|
|
1177
|
-
const roleFilterClause = roleFilter ? ` AND Role = '${roleFilter}'` : '';
|
|
1178
|
-
const sql = `SELECT
|
|
1179
|
-
${maxHistoricalMessages ? 'TOP ' + maxHistoricalMessages : ''} *
|
|
1180
|
-
FROM
|
|
1181
|
-
${e.SchemaName}.${e.BaseView}
|
|
1182
|
-
WHERE
|
|
1183
|
-
ConversationID = '${ConversationId}'${roleFilterClause}
|
|
1184
|
-
ORDER
|
|
1185
|
-
BY __mj_CreatedAt DESC`;
|
|
1186
|
-
const request = new mssql.Request(dataSource);
|
|
1187
|
-
const result = await request.query(sql);
|
|
1188
|
-
if (!result || !result.recordset)
|
|
1189
|
-
throw new Error(`Error running SQL: ${sql}`);
|
|
1190
|
-
else {
|
|
1191
|
-
const returnData = result.recordset.sort((a, b) => {
|
|
1192
|
-
const aDate = new Date(a.__mj_CreatedAt);
|
|
1193
|
-
const bDate = new Date(b.__mj_CreatedAt);
|
|
1194
|
-
return aDate.getTime() - bDate.getTime();
|
|
1195
|
-
});
|
|
1196
|
-
return returnData.map((r) => {
|
|
1197
|
-
const skipRole = this.MapDBRoleToSkipRole(r.Role);
|
|
1198
|
-
let outputMessage;
|
|
1199
|
-
if (skipRole === 'system') {
|
|
1200
|
-
let detail;
|
|
1201
|
-
try {
|
|
1202
|
-
detail = JSON.parse(r.Message);
|
|
1203
|
-
}
|
|
1204
|
-
catch (e) {
|
|
1205
|
-
detail = null;
|
|
1206
|
-
outputMessage = r.Message;
|
|
1207
|
-
}
|
|
1208
|
-
if (detail?.responsePhase === SkipResponsePhase.AnalysisComplete) {
|
|
1209
|
-
const analysisDetail = detail;
|
|
1210
|
-
outputMessage = JSON.stringify({
|
|
1211
|
-
responsePhase: SkipResponsePhase.AnalysisComplete,
|
|
1212
|
-
techExplanation: analysisDetail.techExplanation,
|
|
1213
|
-
userExplanation: analysisDetail.userExplanation,
|
|
1214
|
-
executionResults: analysisDetail.executionResults,
|
|
1215
|
-
tableDataColumns: analysisDetail.tableDataColumns,
|
|
1216
|
-
componentOptions: analysisDetail.componentOptions,
|
|
1217
|
-
artifactRequest: analysisDetail.artifactRequest
|
|
1218
|
-
});
|
|
1219
|
-
}
|
|
1220
|
-
else if (detail?.responsePhase === SkipResponsePhase.ClarifyingQuestion) {
|
|
1221
|
-
const clarifyingQuestionDetail = detail;
|
|
1222
|
-
outputMessage = JSON.stringify({
|
|
1223
|
-
responsePhase: SkipResponsePhase.ClarifyingQuestion,
|
|
1224
|
-
clarifyingQuestion: clarifyingQuestionDetail.clarifyingQuestion,
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
else if (detail) {
|
|
1228
|
-
LogError(`Unknown response phase: ${detail.responsePhase}`);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
const m = {
|
|
1232
|
-
content: skipRole === 'system' ? outputMessage : r.Message,
|
|
1233
|
-
role: skipRole,
|
|
1234
|
-
conversationDetailID: r.ID,
|
|
1235
|
-
hiddenToUser: r.HiddenToUser,
|
|
1236
|
-
userRating: r.UserRating,
|
|
1237
|
-
userFeedback: r.UserFeedback,
|
|
1238
|
-
reflectionInsights: r.ReflectionInsights,
|
|
1239
|
-
summaryOfEarlierConveration: r.SummaryOfEarlierConversation,
|
|
1240
|
-
createdAt: r.__mj_CreatedAt,
|
|
1241
|
-
updatedAt: r.__mj_UpdatedAt,
|
|
1242
|
-
};
|
|
1243
|
-
return m;
|
|
1244
|
-
});
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
catch (e) {
|
|
1248
|
-
LogError(e);
|
|
1249
|
-
throw e;
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
MapDBRoleToSkipRole(role) {
|
|
1253
|
-
switch (role.trim().toLowerCase()) {
|
|
1254
|
-
case 'ai':
|
|
1255
|
-
case 'system':
|
|
1256
|
-
case 'assistant':
|
|
1257
|
-
return 'system';
|
|
1258
|
-
default:
|
|
1259
|
-
return 'user';
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
async HandleSkipChatRequest(input, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, md, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime) {
|
|
1263
|
-
const skipConfigInfo = configInfo.askSkip;
|
|
1264
|
-
const chatURL = skipConfigInfo.url ? `${skipConfigInfo.url}${SKIP_API_ENDPOINTS.CHAT}` : skipConfigInfo.chatURL;
|
|
1265
|
-
LogStatus(` >>> HandleSkipRequest: Sending request to Skip API: ${chatURL}`);
|
|
1266
|
-
if (conversationDetailCount > 10) {
|
|
1267
|
-
await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
|
|
1268
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
1269
|
-
message: JSON.stringify({
|
|
1270
|
-
type: 'AskSkip',
|
|
1271
|
-
status: 'Error',
|
|
1272
|
-
conversationID: ConversationId,
|
|
1273
|
-
message: 'Analysis failed to run, please try again later and if this continues, contact your support desk.',
|
|
1274
|
-
}),
|
|
1275
|
-
sessionId: userPayload.sessionId,
|
|
1276
|
-
});
|
|
1277
|
-
return {
|
|
1278
|
-
Success: false,
|
|
1279
|
-
Status: 'Error',
|
|
1280
|
-
Result: `Exceeded maximum attempts to answer the question ${UserQuestion}`,
|
|
1281
|
-
ResponsePhase: SkipResponsePhase.AnalysisComplete,
|
|
1282
|
-
ConversationId: ConversationId,
|
|
1283
|
-
UserMessageConversationDetailId: '',
|
|
1284
|
-
AIMessageConversationDetailId: '',
|
|
1285
|
-
};
|
|
1286
|
-
}
|
|
1287
|
-
let response;
|
|
1288
|
-
try {
|
|
1289
|
-
response = await sendPostRequest(chatURL, input, true, this.buildSkipPostHeaders(), (message) => {
|
|
1290
|
-
LogStatus(JSON.stringify(message, null, 4));
|
|
1291
|
-
if (message.type === 'status_update') {
|
|
1292
|
-
const statusContent = message.value.messages[0].content;
|
|
1293
|
-
activeStreams.updateStatus(ConversationId, statusContent, userPayload.sessionId);
|
|
1294
|
-
const sessionIds = activeStreams.getSessionIds(ConversationId);
|
|
1295
|
-
for (const sessionId of sessionIds) {
|
|
1296
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
1297
|
-
message: JSON.stringify({
|
|
1298
|
-
type: 'AskSkip',
|
|
1299
|
-
status: 'OK',
|
|
1300
|
-
conversationID: ConversationId,
|
|
1301
|
-
ResponsePhase: message.value.responsePhase,
|
|
1302
|
-
message: statusContent,
|
|
1303
|
-
}),
|
|
1304
|
-
sessionId: sessionId,
|
|
1305
|
-
});
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
});
|
|
1309
|
-
}
|
|
1310
|
-
catch (error) {
|
|
1311
|
-
await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
|
|
1312
|
-
LogError(`Error in HandleSkipChatRequest sendPostRequest: ${error}`);
|
|
1313
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
1314
|
-
message: JSON.stringify({
|
|
1315
|
-
type: 'AskSkip',
|
|
1316
|
-
status: 'Error',
|
|
1317
|
-
conversationID: ConversationId,
|
|
1318
|
-
message: 'Request failed. Please try again later and if this continues, contact your support desk.',
|
|
1319
|
-
}),
|
|
1320
|
-
sessionId: userPayload.sessionId,
|
|
1321
|
-
});
|
|
1322
|
-
throw error;
|
|
1323
|
-
}
|
|
1324
|
-
if (response && response.length > 0) {
|
|
1325
|
-
const apiResponse = response[response.length - 1].value;
|
|
1326
|
-
LogStatus(` Skip API response: ${apiResponse.responsePhase}`);
|
|
1327
|
-
this.PublishApiResponseUserUpdateMessage(apiResponse, userPayload, ConversationId, pubSub);
|
|
1328
|
-
if (apiResponse.responsePhase === 'data_request') {
|
|
1329
|
-
return await this.HandleDataRequestPhase(input, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime);
|
|
1330
|
-
}
|
|
1331
|
-
else if (apiResponse.responsePhase === 'clarifying_question') {
|
|
1332
|
-
return await this.HandleClarifyingQuestionPhase(input, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, startTime);
|
|
1333
|
-
}
|
|
1334
|
-
else if (apiResponse.responsePhase === 'analysis_complete') {
|
|
1335
|
-
return await this.HandleAnalysisComplete(input, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, startTime);
|
|
1336
|
-
}
|
|
1337
|
-
else {
|
|
1338
|
-
throw new Error(`Unknown Skip API response phase: ${apiResponse.responsePhase}`);
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
else {
|
|
1342
|
-
await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
|
|
1343
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
1344
|
-
message: JSON.stringify({
|
|
1345
|
-
type: 'AskSkip',
|
|
1346
|
-
status: 'Error',
|
|
1347
|
-
conversationID: ConversationId,
|
|
1348
|
-
message: 'Analysis failed to run, please try again later and if this continues, contact your support desk.',
|
|
1349
|
-
}),
|
|
1350
|
-
sessionId: userPayload.sessionId,
|
|
1351
|
-
});
|
|
1352
|
-
return {
|
|
1353
|
-
Success: false,
|
|
1354
|
-
Status: 'Error',
|
|
1355
|
-
Result: `User Question ${UserQuestion} didn't work!`,
|
|
1356
|
-
ResponsePhase: SkipResponsePhase.AnalysisComplete,
|
|
1357
|
-
ConversationId: ConversationId,
|
|
1358
|
-
UserMessageConversationDetailId: '',
|
|
1359
|
-
AIMessageConversationDetailId: '',
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
buildSkipPostHeaders() {
|
|
1364
|
-
return {
|
|
1365
|
-
'x-api-key': configInfo.askSkip?.apiKey ?? '',
|
|
1366
|
-
};
|
|
1367
|
-
}
|
|
1368
|
-
async PublishApiResponseUserUpdateMessage(apiResponse, userPayload, conversationID, pubSub) {
|
|
1369
|
-
let sUserMessage = '';
|
|
1370
|
-
switch (apiResponse.responsePhase) {
|
|
1371
|
-
case 'data_request':
|
|
1372
|
-
sUserMessage = 'We need to gather some more data, I will do that next and update you soon.';
|
|
1373
|
-
break;
|
|
1374
|
-
case 'analysis_complete':
|
|
1375
|
-
sUserMessage = 'I have completed the analysis, the results will be available momentarily.';
|
|
1376
|
-
break;
|
|
1377
|
-
case 'clarifying_question':
|
|
1378
|
-
break;
|
|
1379
|
-
}
|
|
1380
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
1381
|
-
message: JSON.stringify({
|
|
1382
|
-
type: 'AskSkip',
|
|
1383
|
-
status: 'OK',
|
|
1384
|
-
conversationID,
|
|
1385
|
-
message: sUserMessage,
|
|
1386
|
-
}),
|
|
1387
|
-
sessionId: userPayload.sessionId,
|
|
1388
|
-
});
|
|
1389
|
-
}
|
|
1390
|
-
async HandleAnalysisComplete(apiRequest, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, startTime) {
|
|
1391
|
-
const md = new Metadata();
|
|
1392
|
-
if (apiRequest.callingServerAccessToken && tokenExists(apiRequest.callingServerAccessToken)) {
|
|
1393
|
-
deleteAccessToken(apiRequest.callingServerAccessToken);
|
|
1394
|
-
}
|
|
1395
|
-
const { AIMessageConversationDetailID } = await this.FinishConversationAndNotifyUser(apiResponse, dataContext, dataContextEntity, md, user, convoEntity, pubSub, userPayload, dataSource, startTime);
|
|
1396
|
-
const response = {
|
|
1397
|
-
Success: true,
|
|
1398
|
-
Status: 'OK',
|
|
1399
|
-
ResponsePhase: SkipResponsePhase.AnalysisComplete,
|
|
1400
|
-
ConversationId: ConversationId,
|
|
1401
|
-
UserMessageConversationDetailId: convoDetailEntity.ID,
|
|
1402
|
-
AIMessageConversationDetailId: AIMessageConversationDetailID,
|
|
1403
|
-
Result: JSON.stringify(apiResponse),
|
|
1404
|
-
};
|
|
1405
|
-
return response;
|
|
1406
|
-
}
|
|
1407
|
-
async HandleClarifyingQuestionPhase(apiRequest, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, startTime) {
|
|
1408
|
-
const endTime = new Date();
|
|
1409
|
-
const md = new Metadata();
|
|
1410
|
-
const convoDetailEntityAI = await md.GetEntityObject('Conversation Details', user);
|
|
1411
|
-
convoDetailEntityAI.NewRecord();
|
|
1412
|
-
convoDetailEntityAI.ConversationID = ConversationId;
|
|
1413
|
-
convoDetailEntityAI.Message = JSON.stringify(apiResponse);
|
|
1414
|
-
convoDetailEntityAI.Role = 'AI';
|
|
1415
|
-
convoDetailEntityAI.HiddenToUser = false;
|
|
1416
|
-
convoDetailEntityAI.CompletionTime = endTime.getTime() - startTime.getTime();
|
|
1417
|
-
await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
|
|
1418
|
-
if (await convoDetailEntityAI.Save()) {
|
|
1419
|
-
return {
|
|
1420
|
-
Success: true,
|
|
1421
|
-
Status: 'OK',
|
|
1422
|
-
ResponsePhase: SkipResponsePhase.ClarifyingQuestion,
|
|
1423
|
-
ConversationId: ConversationId,
|
|
1424
|
-
UserMessageConversationDetailId: convoDetailEntity.ID,
|
|
1425
|
-
AIMessageConversationDetailId: convoDetailEntityAI.ID,
|
|
1426
|
-
Result: JSON.stringify(apiResponse),
|
|
1427
|
-
};
|
|
1428
|
-
}
|
|
1429
|
-
else {
|
|
1430
|
-
LogError(`Error saving conversation detail entity for AI message: ${apiResponse.clarifyingQuestion}`, undefined, convoDetailEntityAI.LatestResult);
|
|
1431
|
-
return {
|
|
1432
|
-
Success: false,
|
|
1433
|
-
Status: 'Error',
|
|
1434
|
-
ResponsePhase: SkipResponsePhase.ClarifyingQuestion,
|
|
1435
|
-
ConversationId: ConversationId,
|
|
1436
|
-
UserMessageConversationDetailId: convoDetailEntity.ID,
|
|
1437
|
-
AIMessageConversationDetailId: convoDetailEntityAI.ID,
|
|
1438
|
-
Result: JSON.stringify(apiResponse),
|
|
1439
|
-
};
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
async HandleDataRequestPhase(apiRequest, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime) {
|
|
1443
|
-
try {
|
|
1444
|
-
if (!apiResponse.success) {
|
|
1445
|
-
LogError(`Data request/gathering from Skip API failed: ${apiResponse.error}`);
|
|
1446
|
-
return {
|
|
1447
|
-
Success: false,
|
|
1448
|
-
Status: `The Skip API Server data gathering phase returned a non-recoverable error. Try again later and Skip might be able to handle this request.\n${apiResponse.error}`,
|
|
1449
|
-
ResponsePhase: SkipResponsePhase.DataRequest,
|
|
1450
|
-
ConversationId: ConversationId,
|
|
1451
|
-
UserMessageConversationDetailId: convoDetailEntity.ID,
|
|
1452
|
-
AIMessageConversationDetailId: '',
|
|
1453
|
-
Result: JSON.stringify(apiResponse),
|
|
1454
|
-
};
|
|
1455
|
-
}
|
|
1456
|
-
const _maxDataGatheringRetries = 5;
|
|
1457
|
-
const _dataGatheringFailureHeaderMessage = '***DATA GATHERING FAILURE***';
|
|
1458
|
-
const md = new Metadata();
|
|
1459
|
-
const executionErrors = [];
|
|
1460
|
-
let dataRequest = apiResponse.dataRequest;
|
|
1461
|
-
apiRequest.messages.push({
|
|
1462
|
-
content: `Skip API Requested Data as shown below
|
|
1463
|
-
${JSON.stringify(apiResponse.dataRequest)}`,
|
|
1464
|
-
role: 'system',
|
|
1465
|
-
conversationDetailID: convoDetailEntity.ID,
|
|
1466
|
-
});
|
|
1467
|
-
if (!Array.isArray(dataRequest)) {
|
|
1468
|
-
if (dataRequest) {
|
|
1469
|
-
dataRequest = [dataRequest];
|
|
1470
|
-
}
|
|
1471
|
-
else {
|
|
1472
|
-
const errorMessage = `Data request from Skip API is not an array and not a single item.`;
|
|
1473
|
-
LogError(errorMessage);
|
|
1474
|
-
executionErrors.push({ dataRequest: apiResponse.dataRequest, errorMessage: errorMessage });
|
|
1475
|
-
dataRequest = [];
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
for (const dr of dataRequest) {
|
|
1479
|
-
try {
|
|
1480
|
-
const item = dataContext.AddDataContextItem();
|
|
1481
|
-
switch (dr.type) {
|
|
1482
|
-
case 'sql':
|
|
1483
|
-
item.Type = 'sql';
|
|
1484
|
-
item.SQL = dr.text;
|
|
1485
|
-
item.AdditionalDescription = dr.description;
|
|
1486
|
-
item.CodeName = dr.codeName;
|
|
1487
|
-
if (!(await item.LoadData(dataSource, false, false, 0, user)))
|
|
1488
|
-
throw new Error(`SQL data request failed: ${item.DataLoadingError}`);
|
|
1489
|
-
break;
|
|
1490
|
-
case 'stored_query':
|
|
1491
|
-
const queryName = dr.text;
|
|
1492
|
-
const query = md.Queries.find((q) => q.Name === queryName);
|
|
1493
|
-
if (query) {
|
|
1494
|
-
item.Type = 'query';
|
|
1495
|
-
item.QueryID = query.ID;
|
|
1496
|
-
item.RecordName = query.Name;
|
|
1497
|
-
item.AdditionalDescription = dr.description;
|
|
1498
|
-
if (!(await item.LoadData(dataSource, false, false, 0, user)))
|
|
1499
|
-
throw new Error(`SQL data request failed: ${item.DataLoadingError}`);
|
|
1500
|
-
}
|
|
1501
|
-
else
|
|
1502
|
-
throw new Error(`Query ${queryName} not found.`);
|
|
1503
|
-
break;
|
|
1504
|
-
default:
|
|
1505
|
-
throw new Error(`Unknown data request type: ${dr.type}`);
|
|
1506
|
-
break;
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
catch (e) {
|
|
1510
|
-
LogError(e);
|
|
1511
|
-
executionErrors.push({
|
|
1512
|
-
dataRequest: dr,
|
|
1513
|
-
errorMessage: e && typeof e === 'object' && 'message' in e && e.message ? e.message : e.toString(),
|
|
1514
|
-
});
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
if (executionErrors.length > 0) {
|
|
1518
|
-
const dataGatheringFailedAttemptCount = apiRequest.messages.filter((m) => m.content.includes(_dataGatheringFailureHeaderMessage)).length + 1;
|
|
1519
|
-
if (dataGatheringFailedAttemptCount > _maxDataGatheringRetries) {
|
|
1520
|
-
LogStatus(`Execution errors for Skip data request occured, and we have exceeded the max retries${_maxDataGatheringRetries}, sending errors back to the user.`);
|
|
1521
|
-
return {
|
|
1522
|
-
Success: false,
|
|
1523
|
-
Status: 'Error gathering data and we have exceedded the max retries. Try again later and Skip might be able to handle this request.',
|
|
1524
|
-
ResponsePhase: SkipResponsePhase.DataRequest,
|
|
1525
|
-
ConversationId: ConversationId,
|
|
1526
|
-
UserMessageConversationDetailId: convoDetailEntity.ID,
|
|
1527
|
-
AIMessageConversationDetailId: '',
|
|
1528
|
-
Result: JSON.stringify(apiResponse),
|
|
1529
|
-
};
|
|
1530
|
-
}
|
|
1531
|
-
else {
|
|
1532
|
-
LogStatus(`Execution errors for Skip data request occured, sending those errors back to the Skip API to get new instructions.`);
|
|
1533
|
-
apiRequest.requestPhase = 'data_gathering_failure';
|
|
1534
|
-
apiRequest.messages.push({
|
|
1535
|
-
content: `${_dataGatheringFailureHeaderMessage} #${dataGatheringFailedAttemptCount} of ${_maxDataGatheringRetries} attempts to gather data failed. Errors:
|
|
1536
|
-
${JSON.stringify(executionErrors)}
|
|
1537
|
-
`,
|
|
1538
|
-
role: 'user',
|
|
1539
|
-
conversationDetailID: convoDetailEntity.ID,
|
|
1540
|
-
});
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
else {
|
|
1544
|
-
await dataContext.SaveItems(user, false);
|
|
1545
|
-
apiRequest.dataContext = CopyScalarsAndArrays(dataContext);
|
|
1546
|
-
apiRequest.requestPhase = 'data_gathering_response';
|
|
1547
|
-
}
|
|
1548
|
-
conversationDetailCount++;
|
|
1549
|
-
return this.HandleSkipChatRequest(apiRequest, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, md, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime);
|
|
1550
|
-
}
|
|
1551
|
-
catch (e) {
|
|
1552
|
-
LogError(e);
|
|
1553
|
-
throw e;
|
|
1554
|
-
}
|
|
1555
|
-
}
|
|
1556
|
-
async FinishConversationAndNotifyUser(apiResponse, dataContext, dataContextEntity, md, user, convoEntity, pubSub, userPayload, dataSource, startTime) {
|
|
1557
|
-
const sTitle = apiResponse.title || apiResponse.reportTitle;
|
|
1558
|
-
const sResult = JSON.stringify(apiResponse);
|
|
1559
|
-
let artifactId = null;
|
|
1560
|
-
let artifactVersionId = null;
|
|
1561
|
-
if (apiResponse.artifactRequest?.action === 'new_artifact' || apiResponse.artifactRequest?.action === 'new_artifact_version') {
|
|
1562
|
-
artifactId = apiResponse.artifactRequest.artifactId;
|
|
1563
|
-
let newVersion = 0;
|
|
1564
|
-
if (apiResponse.artifactRequest?.action === 'new_artifact') {
|
|
1565
|
-
const artifactEntity = await md.GetEntityObject('MJ: Conversation Artifacts', user);
|
|
1566
|
-
artifactEntity.NewRecord();
|
|
1567
|
-
artifactEntity.ConversationID = convoEntity.ID;
|
|
1568
|
-
artifactEntity.Name = apiResponse.artifactRequest.name;
|
|
1569
|
-
artifactEntity.Description = apiResponse.artifactRequest.description;
|
|
1570
|
-
await AIEngine.Instance.Config(false, user);
|
|
1571
|
-
artifactEntity.ArtifactTypeID = AIEngine.Instance.ArtifactTypes.find((t) => t.Name === 'Report')?.ID;
|
|
1572
|
-
artifactEntity.SharingScope = 'None';
|
|
1573
|
-
if (await artifactEntity.Save()) {
|
|
1574
|
-
artifactId = artifactEntity.ID;
|
|
1575
|
-
}
|
|
1576
|
-
else {
|
|
1577
|
-
LogError(`Error saving artifact entity for conversation: ${convoEntity.ID}`, undefined, artifactEntity.LatestResult);
|
|
1578
|
-
}
|
|
1579
|
-
newVersion = 1;
|
|
1580
|
-
}
|
|
1581
|
-
else {
|
|
1582
|
-
const ei = md.EntityByName("MJ: Conversation Artifact Versions");
|
|
1583
|
-
const sSQL = `SELECT ISNULL(MAX(Version),0) AS MaxVersion FROM [${ei.SchemaName}].[${ei.BaseView}] WHERE ConversationArtifactID = '${artifactId}'`;
|
|
1584
|
-
try {
|
|
1585
|
-
const request = new mssql.Request(dataSource);
|
|
1586
|
-
const result = await request.query(sSQL);
|
|
1587
|
-
if (result && result.recordset && result.recordset.length > 0) {
|
|
1588
|
-
newVersion = result.recordset[0].MaxVersion + 1;
|
|
1589
|
-
}
|
|
1590
|
-
else {
|
|
1591
|
-
LogError(`Error getting max version for artifact ID: ${artifactId}`, undefined, result);
|
|
1592
|
-
}
|
|
1593
|
-
}
|
|
1594
|
-
catch (e) {
|
|
1595
|
-
LogError(`Error getting max version for artifact ID: ${artifactId}`, undefined, e);
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
if (artifactId && newVersion > 0) {
|
|
1599
|
-
const artifactVersionEntity = await md.GetEntityObject('MJ: Conversation Artifact Versions', user);
|
|
1600
|
-
artifactVersionEntity.NewRecord();
|
|
1601
|
-
artifactVersionEntity.ConversationArtifactID = artifactId;
|
|
1602
|
-
artifactVersionEntity.Version = newVersion;
|
|
1603
|
-
artifactVersionEntity.Configuration = sResult;
|
|
1604
|
-
if (await artifactVersionEntity.Save()) {
|
|
1605
|
-
artifactVersionId = artifactVersionEntity.ID;
|
|
1606
|
-
}
|
|
1607
|
-
else {
|
|
1608
|
-
LogError(`Error saving Artifact Version record`);
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
}
|
|
1612
|
-
const endTime = new Date();
|
|
1613
|
-
const convoDetailEntityAI = await md.GetEntityObject('Conversation Details', user);
|
|
1614
|
-
convoDetailEntityAI.NewRecord();
|
|
1615
|
-
convoDetailEntityAI.ConversationID = convoEntity.ID;
|
|
1616
|
-
convoDetailEntityAI.Message = sResult;
|
|
1617
|
-
convoDetailEntityAI.Role = 'AI';
|
|
1618
|
-
convoDetailEntityAI.HiddenToUser = false;
|
|
1619
|
-
convoDetailEntityAI.CompletionTime = endTime.getTime() - startTime.getTime();
|
|
1620
|
-
if (artifactId && artifactId.length > 0) {
|
|
1621
|
-
convoDetailEntityAI.ArtifactID = artifactId;
|
|
1622
|
-
if (artifactVersionId && artifactVersionId.length > 0) {
|
|
1623
|
-
convoDetailEntityAI.ArtifactVersionID = artifactVersionId;
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
const convoDetailSaveResult = await convoDetailEntityAI.Save();
|
|
1627
|
-
if (!convoDetailSaveResult) {
|
|
1628
|
-
LogError(`Error saving conversation detail entity for AI message: ${sResult}`, undefined, convoDetailEntityAI.LatestResult);
|
|
1629
|
-
}
|
|
1630
|
-
let needToSaveConvo = false;
|
|
1631
|
-
if (convoEntity.Name === AskSkipResolver_1._defaultNewChatName && sTitle && sTitle !== AskSkipResolver_1._defaultNewChatName) {
|
|
1632
|
-
convoEntity.Name = sTitle;
|
|
1633
|
-
needToSaveConvo = true;
|
|
1634
|
-
}
|
|
1635
|
-
if (convoEntity.Status === 'Processing') {
|
|
1636
|
-
convoEntity.Status = 'Available';
|
|
1637
|
-
needToSaveConvo = true;
|
|
1638
|
-
}
|
|
1639
|
-
if (needToSaveConvo) {
|
|
1640
|
-
const convoEntitySaveResult = await convoEntity.Save();
|
|
1641
|
-
if (!convoEntitySaveResult) {
|
|
1642
|
-
LogError(`Error saving conversation entity for AI message: ${sResult}`, undefined, convoEntity.LatestResult);
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
const userNotification = await md.GetEntityObject('User Notifications', user);
|
|
1646
|
-
userNotification.NewRecord();
|
|
1647
|
-
userNotification.UserID = user.ID;
|
|
1648
|
-
userNotification.Title = 'Report Created: ' + sTitle;
|
|
1649
|
-
userNotification.Message = `Good news! Skip finished creating a report for you, click on this notification to jump back into the conversation.`;
|
|
1650
|
-
userNotification.Unread = true;
|
|
1651
|
-
userNotification.ResourceConfiguration = JSON.stringify({
|
|
1652
|
-
type: 'askskip',
|
|
1653
|
-
conversationId: convoEntity.ID,
|
|
1654
|
-
});
|
|
1655
|
-
const userNotificationSaveResult = await userNotification.Save();
|
|
1656
|
-
if (!userNotificationSaveResult) {
|
|
1657
|
-
LogError(`Error saving user notification entity for AI message: ${sResult}`, undefined, userNotification.LatestResult);
|
|
1658
|
-
}
|
|
1659
|
-
if (apiResponse.newDataItems) {
|
|
1660
|
-
apiResponse.newDataItems.forEach((skipItem) => {
|
|
1661
|
-
const newItem = dataContext.AddDataContextItem();
|
|
1662
|
-
newItem.Type = 'sql';
|
|
1663
|
-
newItem.SQL = skipItem.text;
|
|
1664
|
-
newItem.AdditionalDescription = skipItem.description;
|
|
1665
|
-
});
|
|
1666
|
-
}
|
|
1667
|
-
await dataContext.SaveItems(user, false);
|
|
1668
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
1669
|
-
message: JSON.stringify({
|
|
1670
|
-
type: 'UserNotifications',
|
|
1671
|
-
status: 'OK',
|
|
1672
|
-
conversationID: convoEntity.ID,
|
|
1673
|
-
details: {
|
|
1674
|
-
action: 'create',
|
|
1675
|
-
recordId: userNotification.ID,
|
|
1676
|
-
},
|
|
1677
|
-
}),
|
|
1678
|
-
sessionId: userPayload.sessionId,
|
|
1679
|
-
});
|
|
1680
|
-
return {
|
|
1681
|
-
AIMessageConversationDetailID: convoDetailEntityAI.ID,
|
|
1682
|
-
};
|
|
1683
|
-
}
|
|
1684
|
-
async setConversationStatus(convoEntity, status, userPayload, pubSub) {
|
|
1685
|
-
if (convoEntity.Status !== status) {
|
|
1686
|
-
convoEntity.Status = status;
|
|
1687
|
-
const convoSaveResult = await convoEntity.Save();
|
|
1688
|
-
if (!convoSaveResult) {
|
|
1689
|
-
LogError(`Error updating conversation status to '${status}'`, undefined, convoEntity.LatestResult);
|
|
1690
|
-
}
|
|
1691
|
-
else {
|
|
1692
|
-
if (status === 'Available') {
|
|
1693
|
-
activeStreams.removeConversation(convoEntity.ID);
|
|
1694
|
-
LogStatus(`Removed conversation ${convoEntity.ID} from active streams (status changed to Available)`);
|
|
1695
|
-
}
|
|
1696
|
-
else if (status === 'Processing') {
|
|
1697
|
-
activeStreams.addSession(convoEntity.ID, userPayload.sessionId);
|
|
1698
|
-
LogStatus(`Added session ${userPayload.sessionId} to active streams for conversation ${convoEntity.ID}`);
|
|
1699
|
-
}
|
|
1700
|
-
if (pubSub) {
|
|
1701
|
-
const statusMessage = {
|
|
1702
|
-
type: 'ConversationStatusUpdate',
|
|
1703
|
-
conversationID: convoEntity.ID,
|
|
1704
|
-
status: status,
|
|
1705
|
-
timestamp: new Date().toISOString()
|
|
1706
|
-
};
|
|
1707
|
-
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
1708
|
-
pushStatusUpdates: {
|
|
1709
|
-
message: JSON.stringify(statusMessage),
|
|
1710
|
-
sessionId: userPayload.sessionId
|
|
1711
|
-
}
|
|
1712
|
-
});
|
|
1713
|
-
LogStatus(`Published conversation status update for ${convoEntity.ID}: ${status}`);
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
return convoSaveResult;
|
|
1717
|
-
}
|
|
1718
|
-
return true;
|
|
1719
|
-
}
|
|
1720
|
-
getAgentNoteTypeIDByName(name, defaultNoteType = 'AI') {
|
|
1721
|
-
const noteTypeID = AIEngine.Instance.AgentNoteTypes.find(nt => nt.Name.trim().toLowerCase() === name.trim().toLowerCase())?.ID;
|
|
1722
|
-
if (noteTypeID) {
|
|
1723
|
-
return noteTypeID;
|
|
1724
|
-
}
|
|
1725
|
-
else {
|
|
1726
|
-
const defaultNoteTypeID = AIEngine.Instance.AgentNoteTypes.find(nt => nt.Name.trim().toLowerCase() === defaultNoteType.trim().toLowerCase())?.ID;
|
|
1727
|
-
return defaultNoteTypeID;
|
|
1728
|
-
}
|
|
1729
|
-
}
|
|
1730
|
-
async getViewData(ViewId, user) {
|
|
1731
|
-
const rv = new RunView();
|
|
1732
|
-
const result = await rv.RunView({ ViewID: ViewId, IgnoreMaxRows: true }, user);
|
|
1733
|
-
if (result && result.Success)
|
|
1734
|
-
return result.Results;
|
|
1735
|
-
else
|
|
1736
|
-
throw new Error(`Error running view ${ViewId}`);
|
|
1737
|
-
}
|
|
1738
|
-
};
|
|
1739
|
-
__decorate([
|
|
1740
|
-
Query(() => AskSkipResultType),
|
|
1741
|
-
__param(0, Arg('UserQuestion', () => String)),
|
|
1742
|
-
__param(1, Arg('ConversationId', () => String)),
|
|
1743
|
-
__param(2, Arg('EntityName', () => String)),
|
|
1744
|
-
__param(3, Arg('CompositeKey', () => CompositeKeyInputType)),
|
|
1745
|
-
__param(4, Ctx()),
|
|
1746
|
-
__param(5, PubSub()),
|
|
1747
|
-
__metadata("design:type", Function),
|
|
1748
|
-
__metadata("design:paramtypes", [String, String, String, CompositeKeyInputType, Object, PubSubEngine]),
|
|
1749
|
-
__metadata("design:returntype", Promise)
|
|
1750
|
-
], AskSkipResolver.prototype, "ExecuteAskSkipRecordChat", null);
|
|
1751
|
-
__decorate([
|
|
1752
|
-
Query(() => AskSkipResultType),
|
|
1753
|
-
__param(0, Ctx()),
|
|
1754
|
-
__param(1, PubSub()),
|
|
1755
|
-
__param(2, Arg('DataContextId', () => String)),
|
|
1756
|
-
__param(3, Arg('ScriptText', () => String)),
|
|
1757
|
-
__metadata("design:type", Function),
|
|
1758
|
-
__metadata("design:paramtypes", [Object, PubSubEngine, String, String]),
|
|
1759
|
-
__metadata("design:returntype", Promise)
|
|
1760
|
-
], AskSkipResolver.prototype, "ExecuteAskSkipRunScript", null);
|
|
1761
|
-
__decorate([
|
|
1762
|
-
Query(() => ReattachConversationResponse),
|
|
1763
|
-
__param(0, Arg('ConversationId', () => String)),
|
|
1764
|
-
__param(1, Ctx()),
|
|
1765
|
-
__param(2, PubSub()),
|
|
1766
|
-
__metadata("design:type", Function),
|
|
1767
|
-
__metadata("design:paramtypes", [String, Object, PubSubEngine]),
|
|
1768
|
-
__metadata("design:returntype", Promise)
|
|
1769
|
-
], AskSkipResolver.prototype, "ReattachToProcessingConversation", null);
|
|
1770
|
-
__decorate([
|
|
1771
|
-
Query(() => AskSkipResultType),
|
|
1772
|
-
__param(0, Arg('UserQuestion', () => String)),
|
|
1773
|
-
__param(1, Arg('ConversationId', () => String)),
|
|
1774
|
-
__param(2, Ctx()),
|
|
1775
|
-
__param(3, PubSub()),
|
|
1776
|
-
__param(4, Arg('DataContextId', () => String, { nullable: true })),
|
|
1777
|
-
__param(5, Arg('ForceEntityRefresh', () => Boolean, { nullable: true })),
|
|
1778
|
-
__param(6, Arg('StartTime', () => Date, { nullable: true })),
|
|
1779
|
-
__metadata("design:type", Function),
|
|
1780
|
-
__metadata("design:paramtypes", [String, String, Object, PubSubEngine, String, Boolean, Date]),
|
|
1781
|
-
__metadata("design:returntype", Promise)
|
|
1782
|
-
], AskSkipResolver.prototype, "ExecuteAskSkipAnalysisQuery", null);
|
|
1783
|
-
AskSkipResolver = AskSkipResolver_1 = __decorate([
|
|
1784
|
-
Resolver(AskSkipResultType)
|
|
1785
|
-
], AskSkipResolver);
|
|
1786
|
-
export { AskSkipResolver };
|
|
1787
|
-
export default AskSkipResolver;
|
|
1788
|
-
//# sourceMappingURL=AskSkipResolver.js.map
|