@memberjunction/server 2.112.0 → 2.113.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/skip-agent.d.ts +4 -4
- package/dist/agents/skip-agent.d.ts.map +1 -1
- package/dist/agents/skip-agent.js +951 -808
- package/dist/agents/skip-agent.js.map +1 -1
- package/dist/agents/skip-sdk.d.ts +1 -1
- package/dist/agents/skip-sdk.d.ts.map +1 -1
- package/dist/agents/skip-sdk.js +43 -53
- package/dist/agents/skip-sdk.js.map +1 -1
- package/dist/apolloServer/index.js +1 -1
- package/dist/auth/AuthProviderFactory.d.ts +1 -1
- package/dist/auth/AuthProviderFactory.d.ts.map +1 -1
- package/dist/auth/AuthProviderFactory.js +3 -1
- package/dist/auth/AuthProviderFactory.js.map +1 -1
- package/dist/auth/BaseAuthProvider.d.ts +1 -1
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/BaseAuthProvider.js +2 -3
- package/dist/auth/BaseAuthProvider.js.map +1 -1
- package/dist/auth/IAuthProvider.d.ts +1 -1
- package/dist/auth/IAuthProvider.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +1 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +6 -6
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.js +1 -1
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/newUsers.d.ts +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +7 -7
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts.map +1 -1
- package/dist/auth/providers/Auth0Provider.js +1 -1
- package/dist/auth/providers/Auth0Provider.js.map +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts.map +1 -1
- package/dist/auth/providers/CognitoProvider.js +6 -3
- package/dist/auth/providers/CognitoProvider.js.map +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts.map +1 -1
- package/dist/auth/providers/GoogleProvider.js +1 -1
- package/dist/auth/providers/GoogleProvider.js.map +1 -1
- package/dist/auth/providers/MSALProvider.d.ts +1 -1
- package/dist/auth/providers/MSALProvider.d.ts.map +1 -1
- package/dist/auth/providers/MSALProvider.js +1 -1
- package/dist/auth/providers/MSALProvider.js.map +1 -1
- package/dist/auth/providers/OktaProvider.d.ts +1 -1
- package/dist/auth/providers/OktaProvider.d.ts.map +1 -1
- package/dist/auth/providers/OktaProvider.js +1 -1
- package/dist/auth/providers/OktaProvider.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -22
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +7 -9
- package/dist/context.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -1
- package/dist/generated/generated.d.ts +788 -658
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2050 -3054
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/KeyInputOutputTypes.d.ts +1 -1
- package/dist/generic/KeyInputOutputTypes.d.ts.map +1 -1
- package/dist/generic/KeyInputOutputTypes.js +1 -1
- package/dist/generic/KeyInputOutputTypes.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +1 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +10 -15
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +15 -15
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -18
- package/dist/index.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +2 -2
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +30 -28
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +2 -2
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +50 -60
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +38 -36
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +40 -43
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +1 -1
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/EntityResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityResolver.js +1 -1
- package/dist/resolvers/EntityResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +1 -1
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.js +1 -1
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +5 -5
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +6 -8
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +3 -3
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +3 -3
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +11 -11
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.js +1 -1
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +28 -27
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +31 -31
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +9 -9
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +10 -10
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +14 -15
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +44 -48
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskResolver.js +7 -7
- package/dist/resolvers/TaskResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +12 -12
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +1 -1
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +16 -14
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +25 -23
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +21 -17
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.js.map +1 -1
- package/dist/services/ScheduledJobsService.d.ts.map +1 -1
- package/dist/services/ScheduledJobsService.js +6 -4
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/TaskOrchestrator.d.ts +1 -1
- package/dist/services/TaskOrchestrator.d.ts.map +1 -1
- package/dist/services/TaskOrchestrator.js +30 -30
- package/dist/services/TaskOrchestrator.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +2 -2
- package/dist/util.js.map +1 -1
- package/package.json +39 -36
- package/src/agents/skip-agent.ts +1200 -1067
- package/src/agents/skip-sdk.ts +851 -877
- package/src/apolloServer/index.ts +2 -2
- package/src/auth/AuthProviderFactory.ts +14 -8
- package/src/auth/BaseAuthProvider.ts +4 -5
- package/src/auth/IAuthProvider.ts +2 -2
- package/src/auth/exampleNewUserSubClass.ts +2 -9
- package/src/auth/index.ts +26 -31
- package/src/auth/initializeProviders.ts +3 -3
- package/src/auth/newUsers.ts +134 -166
- package/src/auth/providers/Auth0Provider.ts +5 -5
- package/src/auth/providers/CognitoProvider.ts +10 -7
- package/src/auth/providers/GoogleProvider.ts +5 -4
- package/src/auth/providers/MSALProvider.ts +5 -5
- package/src/auth/providers/OktaProvider.ts +7 -6
- package/src/config.ts +54 -63
- package/src/context.ts +30 -42
- package/src/entitySubclasses/entityPermissions.server.ts +3 -3
- package/src/generated/generated.ts +40442 -48106
- package/src/generic/KeyInputOutputTypes.ts +6 -3
- package/src/generic/ResolverBase.ts +78 -119
- package/src/generic/RunViewResolver.ts +23 -27
- package/src/index.ts +48 -66
- package/src/resolvers/ActionResolver.ts +57 -46
- package/src/resolvers/AskSkipResolver.ts +533 -607
- package/src/resolvers/ComponentRegistryResolver.ts +562 -547
- package/src/resolvers/CreateQueryResolver.ts +655 -683
- package/src/resolvers/DatasetResolver.ts +6 -5
- package/src/resolvers/EntityCommunicationsResolver.ts +1 -1
- package/src/resolvers/EntityRecordNameResolver.ts +5 -9
- package/src/resolvers/EntityResolver.ts +7 -9
- package/src/resolvers/FileCategoryResolver.ts +2 -2
- package/src/resolvers/FileResolver.ts +4 -4
- package/src/resolvers/GetDataContextDataResolver.ts +118 -106
- package/src/resolvers/GetDataResolver.ts +205 -194
- package/src/resolvers/MergeRecordsResolver.ts +5 -5
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
- package/src/resolvers/QueryResolver.ts +78 -95
- package/src/resolvers/ReportResolver.ts +2 -2
- package/src/resolvers/RunAIAgentResolver.ts +828 -818
- package/src/resolvers/RunAIPromptResolver.ts +709 -693
- package/src/resolvers/RunTemplateResolver.ts +103 -105
- package/src/resolvers/SqlLoggingConfigResolver.ts +72 -69
- package/src/resolvers/SyncDataResolver.ts +352 -386
- package/src/resolvers/SyncRolesUsersResolver.ts +350 -387
- package/src/resolvers/TaskResolver.ts +115 -110
- package/src/resolvers/TransactionGroupResolver.ts +138 -143
- package/src/resolvers/UserFavoriteResolver.ts +8 -17
- package/src/resolvers/UserViewResolver.ts +12 -17
- package/src/rest/EntityCRUDHandler.ts +268 -291
- package/src/rest/RESTEndpointHandler.ts +776 -782
- package/src/rest/ViewOperationsHandler.ts +195 -191
- package/src/scheduler/LearningCycleScheduler.ts +52 -8
- package/src/services/ScheduledJobsService.ts +132 -129
- package/src/services/TaskOrchestrator.ts +776 -792
- package/src/types.ts +9 -15
- package/src/util.ts +109 -112
package/src/agents/skip-sdk.ts
CHANGED
|
@@ -7,35 +7,26 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
10
|
+
SkipAPIRequest,
|
|
11
|
+
SkipAPIResponse,
|
|
12
|
+
SkipMessage,
|
|
13
|
+
SkipAPIAnalysisCompleteResponse,
|
|
14
|
+
SkipAPIClarifyingQuestionResponse,
|
|
15
|
+
SkipRequestPhase,
|
|
16
|
+
SkipAPIRequestAPIKey,
|
|
17
|
+
SkipQueryInfo,
|
|
18
|
+
SkipEntityInfo,
|
|
19
|
+
SkipEntityFieldInfo,
|
|
20
|
+
SkipEntityFieldValueInfo,
|
|
21
|
+
SkipEntityRelationshipInfo,
|
|
22
|
+
SkipAPIAgentNote,
|
|
23
|
+
SkipAPIAgentNoteType,
|
|
24
|
+
SkipAPIArtifact,
|
|
25
|
+
SkipAPIArtifactVersion,
|
|
26
|
+
SkipAPIArtifactType
|
|
27
27
|
} from '@memberjunction/skip-types';
|
|
28
28
|
import { DataContext } from '@memberjunction/data-context';
|
|
29
|
-
import {
|
|
30
|
-
UserInfo,
|
|
31
|
-
LogStatus,
|
|
32
|
-
LogError,
|
|
33
|
-
Metadata,
|
|
34
|
-
RunQuery,
|
|
35
|
-
EntityInfo,
|
|
36
|
-
EntityFieldInfo,
|
|
37
|
-
EntityRelationshipInfo,
|
|
38
|
-
} from '@memberjunction/global';
|
|
29
|
+
import { UserInfo, LogStatus, LogError, Metadata, RunQuery, EntityInfo, EntityFieldInfo, EntityRelationshipInfo } from '@memberjunction/core';
|
|
39
30
|
import { sendPostRequest } from '../util.js';
|
|
40
31
|
import { configInfo, baseUrl, publicUrl, graphqlPort, graphqlRootPath, apiKey as callbackAPIKey } from '../config.js';
|
|
41
32
|
import { GetAIAPIKey } from '@memberjunction/ai';
|
|
@@ -50,125 +41,125 @@ import { take } from 'rxjs/operators';
|
|
|
50
41
|
* Configuration options for Skip SDK
|
|
51
42
|
*/
|
|
52
43
|
export interface SkipSDKConfig {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Skip API base URL (e.g., 'https://skip.memberjunction.com')
|
|
46
|
+
*/
|
|
47
|
+
apiUrl?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Skip API key for authentication
|
|
51
|
+
*/
|
|
52
|
+
apiKey?: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Organization ID
|
|
56
|
+
*/
|
|
57
|
+
organizationId?: string;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Optional organization context information
|
|
61
|
+
*/
|
|
62
|
+
organizationInfo?: string;
|
|
72
63
|
}
|
|
73
64
|
|
|
74
65
|
/**
|
|
75
66
|
* Options for making a Skip API call
|
|
76
67
|
*/
|
|
77
68
|
export interface SkipCallOptions {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Conversation messages (user/assistant)
|
|
71
|
+
*/
|
|
72
|
+
messages: SkipMessage[];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Conversation ID for tracking
|
|
76
|
+
*/
|
|
77
|
+
conversationId: string;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Data context to provide to Skip
|
|
81
|
+
*/
|
|
82
|
+
dataContext?: DataContext;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Request phase (initial_request, clarify_question_response, etc.)
|
|
86
|
+
*/
|
|
87
|
+
requestPhase?: SkipRequestPhase;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Context user for permissions and metadata
|
|
91
|
+
*/
|
|
92
|
+
contextUser: UserInfo;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Database connection for metadata queries
|
|
96
|
+
*/
|
|
97
|
+
dataSource: mssql.ConnectionPool;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Include entity metadata in request
|
|
101
|
+
*/
|
|
102
|
+
includeEntities?: boolean;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Include saved queries in request
|
|
106
|
+
*/
|
|
107
|
+
includeQueries?: boolean;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Include agent notes in request
|
|
111
|
+
*/
|
|
112
|
+
includeNotes?: boolean;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Include agent requests in request
|
|
116
|
+
*/
|
|
117
|
+
includeRequests?: boolean;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Force refresh of entity metadata cache
|
|
121
|
+
*/
|
|
122
|
+
forceEntityRefresh?: boolean;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Include callback API key and access token for Skip to call back to MJ
|
|
126
|
+
*/
|
|
127
|
+
includeCallbackAuth?: boolean;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Callback for streaming status updates during execution
|
|
131
|
+
*/
|
|
132
|
+
onStatusUpdate?: (message: string, responsePhase?: string) => void;
|
|
142
133
|
}
|
|
143
134
|
|
|
144
135
|
/**
|
|
145
136
|
* Result from a Skip API call
|
|
146
137
|
*/
|
|
147
138
|
export interface SkipCallResult {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Whether the call was successful
|
|
141
|
+
*/
|
|
142
|
+
success: boolean;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The final Skip API response
|
|
146
|
+
*/
|
|
147
|
+
response?: SkipAPIResponse;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Response phase (analysis_complete, clarifying_question, status_update)
|
|
151
|
+
*/
|
|
152
|
+
responsePhase?: string;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Error message if failed
|
|
156
|
+
*/
|
|
157
|
+
error?: string;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* All streaming responses received (including intermediate status updates)
|
|
161
|
+
*/
|
|
162
|
+
allResponses?: any[];
|
|
172
163
|
}
|
|
173
164
|
|
|
174
165
|
/**
|
|
@@ -176,777 +167,760 @@ export interface SkipCallResult {
|
|
|
176
167
|
* Provides a clean interface for calling the Skip SaaS API
|
|
177
168
|
*/
|
|
178
169
|
export class SkipSDK {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
170
|
+
private config: SkipSDKConfig;
|
|
171
|
+
|
|
172
|
+
// Static cache for Skip entities (shared across all instances)
|
|
173
|
+
private static __skipEntitiesCache$: BehaviorSubject<Promise<SkipEntityInfo[]> | null> = new BehaviorSubject<Promise<SkipEntityInfo[]> | null>(null);
|
|
174
|
+
private static __lastRefreshTime: number = 0;
|
|
175
|
+
|
|
176
|
+
constructor(config?: SkipSDKConfig) {
|
|
177
|
+
// Use provided config or fall back to MJ server config
|
|
178
|
+
this.config = {
|
|
179
|
+
apiUrl: config?.apiUrl || configInfo.askSkip?.chatURL,
|
|
180
|
+
apiKey: config?.apiKey || configInfo.askSkip?.apiKey,
|
|
181
|
+
organizationId: config?.organizationId || configInfo.askSkip?.orgID,
|
|
182
|
+
organizationInfo: config?.organizationInfo || configInfo.askSkip?.organizationInfo
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Call the Skip chat API
|
|
188
|
+
*/
|
|
189
|
+
async chat(options: SkipCallOptions): Promise<SkipCallResult> {
|
|
190
|
+
LogStatus(`[SkipSDK] Sending request to Skip API: ${this.config.apiUrl}`);
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
// Build the Skip API request
|
|
194
|
+
const skipRequest = await this.buildSkipRequest(options);
|
|
195
|
+
|
|
196
|
+
// Call Skip API with streaming support
|
|
197
|
+
const responses = await sendPostRequest(
|
|
198
|
+
this.config.apiUrl,
|
|
199
|
+
skipRequest,
|
|
200
|
+
true, // useCompression
|
|
201
|
+
this.buildHeaders(),
|
|
202
|
+
(streamMessage: any) => {
|
|
203
|
+
// Handle streaming status updates
|
|
204
|
+
if (streamMessage.type === 'status_update' && options.onStatusUpdate) {
|
|
205
|
+
const statusContent = streamMessage.value?.messages?.[0]?.content;
|
|
206
|
+
const responsePhase = streamMessage.value?.responsePhase;
|
|
207
|
+
if (statusContent) {
|
|
208
|
+
options.onStatusUpdate(statusContent, responsePhase);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// The last response is the final one
|
|
215
|
+
if (responses && responses.length > 0) {
|
|
216
|
+
const finalResponse = responses[responses.length - 1].value as SkipAPIResponse;
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
success: true,
|
|
220
|
+
response: finalResponse,
|
|
221
|
+
responsePhase: finalResponse.responsePhase,
|
|
222
|
+
allResponses: responses
|
|
223
|
+
};
|
|
224
|
+
} else {
|
|
225
|
+
return {
|
|
226
|
+
success: false,
|
|
227
|
+
error: 'No response received from Skip API'
|
|
228
|
+
};
|
|
220
229
|
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
);
|
|
224
230
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
231
|
+
} catch (error) {
|
|
232
|
+
LogError(`[SkipSDK] Error calling Skip API: ${error}`);
|
|
233
|
+
return {
|
|
234
|
+
success: false,
|
|
235
|
+
error: String(error)
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
228
239
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Build the Skip API request object
|
|
242
|
+
*/
|
|
243
|
+
private async buildSkipRequest(options: SkipCallOptions): Promise<SkipAPIRequest> {
|
|
244
|
+
const {
|
|
245
|
+
messages,
|
|
246
|
+
conversationId,
|
|
247
|
+
dataContext,
|
|
248
|
+
requestPhase = 'initial_request',
|
|
249
|
+
contextUser,
|
|
250
|
+
dataSource,
|
|
251
|
+
includeEntities = true,
|
|
252
|
+
includeQueries = true,
|
|
253
|
+
includeNotes = true,
|
|
254
|
+
includeRequests = false,
|
|
255
|
+
forceEntityRefresh = false,
|
|
256
|
+
includeCallbackAuth = true
|
|
257
|
+
} = options;
|
|
258
|
+
|
|
259
|
+
// Build base request with metadata
|
|
260
|
+
const baseRequest = await this.buildBaseRequest(
|
|
261
|
+
contextUser,
|
|
262
|
+
dataSource,
|
|
263
|
+
includeEntities,
|
|
264
|
+
includeQueries,
|
|
265
|
+
includeNotes,
|
|
266
|
+
includeRequests,
|
|
267
|
+
forceEntityRefresh,
|
|
268
|
+
includeCallbackAuth,
|
|
269
|
+
{ conversationId, requestPhase }
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
// Build artifacts for this conversation
|
|
273
|
+
const artifacts = await this.buildArtifacts(contextUser, dataSource, conversationId);
|
|
274
|
+
|
|
275
|
+
// Process messages: filter delegation messages and enrich with metadata
|
|
276
|
+
const processedMessages = this.processMessages(messages);
|
|
277
|
+
|
|
278
|
+
// Construct the full Skip API request
|
|
279
|
+
const request: SkipAPIRequest = {
|
|
280
|
+
messages: processedMessages,
|
|
281
|
+
conversationID: conversationId,
|
|
282
|
+
dataContext: dataContext ? CopyScalarsAndArrays(dataContext) as DataContext : undefined,
|
|
283
|
+
requestPhase,
|
|
284
|
+
artifacts,
|
|
285
|
+
entities: baseRequest.entities || [],
|
|
286
|
+
queries: baseRequest.queries || [],
|
|
287
|
+
notes: baseRequest.notes,
|
|
288
|
+
noteTypes: baseRequest.noteTypes,
|
|
289
|
+
userEmail: baseRequest.userEmail,
|
|
290
|
+
organizationID: baseRequest.organizationID,
|
|
291
|
+
organizationInfo: baseRequest.organizationInfo,
|
|
292
|
+
apiKeys: baseRequest.apiKeys,
|
|
293
|
+
callingServerURL: baseRequest.callingServerURL,
|
|
294
|
+
callingServerAPIKey: baseRequest.callingServerAPIKey,
|
|
295
|
+
callingServerAccessToken: baseRequest.callingServerAccessToken
|
|
234
296
|
};
|
|
235
|
-
|
|
297
|
+
|
|
298
|
+
return request;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Build base request with metadata, API keys, and callback auth
|
|
303
|
+
*/
|
|
304
|
+
private async buildBaseRequest(
|
|
305
|
+
contextUser: UserInfo,
|
|
306
|
+
dataSource: mssql.ConnectionPool,
|
|
307
|
+
includeEntities: boolean,
|
|
308
|
+
includeQueries: boolean,
|
|
309
|
+
includeNotes: boolean,
|
|
310
|
+
includeRequests: boolean,
|
|
311
|
+
forceEntityRefresh: boolean,
|
|
312
|
+
includeCallbackAuth: boolean,
|
|
313
|
+
additionalTokenInfo: any = {}
|
|
314
|
+
): Promise<Partial<SkipAPIRequest>> {
|
|
315
|
+
const entities = includeEntities ? await this.buildEntities(dataSource, forceEntityRefresh) : [];
|
|
316
|
+
const queries = includeQueries ? this.buildQueries() : [];
|
|
317
|
+
const { notes, noteTypes } = includeNotes ? await this.buildAgentNotes(contextUser) : { notes: [], noteTypes: [] };
|
|
318
|
+
// Note: requests would be built here if includeRequests is true
|
|
319
|
+
|
|
320
|
+
// Setup access token for Skip callbacks if needed
|
|
321
|
+
let accessToken: GetDataAccessToken | undefined;
|
|
322
|
+
if (includeCallbackAuth) {
|
|
323
|
+
const tokenInfo = {
|
|
324
|
+
type: 'skip_api_request',
|
|
325
|
+
userEmail: contextUser.Email,
|
|
326
|
+
userName: contextUser.Name,
|
|
327
|
+
userID: contextUser.ID,
|
|
328
|
+
...additionalTokenInfo
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
accessToken = registerAccessToken(
|
|
332
|
+
undefined,
|
|
333
|
+
1000 * 60 * 10, // 10 minutes
|
|
334
|
+
tokenInfo
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
236
338
|
return {
|
|
237
|
-
|
|
238
|
-
|
|
339
|
+
entities,
|
|
340
|
+
queries,
|
|
341
|
+
notes,
|
|
342
|
+
noteTypes,
|
|
343
|
+
userEmail: contextUser.Email,
|
|
344
|
+
organizationID: this.config.organizationId,
|
|
345
|
+
organizationInfo: this.config.organizationInfo,
|
|
346
|
+
apiKeys: this.buildAPIKeys(),
|
|
347
|
+
callingServerURL: accessToken ? (publicUrl || `${baseUrl}:${graphqlPort}${graphqlRootPath}`) : undefined,
|
|
348
|
+
callingServerAPIKey: accessToken ? callbackAPIKey : undefined,
|
|
349
|
+
callingServerAccessToken: accessToken ? accessToken.Token : undefined
|
|
239
350
|
};
|
|
240
|
-
}
|
|
241
|
-
} catch (error) {
|
|
242
|
-
LogError(`[SkipSDK] Error calling Skip API: ${error}`);
|
|
243
|
-
return {
|
|
244
|
-
success: false,
|
|
245
|
-
error: String(error),
|
|
246
|
-
};
|
|
247
351
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
accessToken = registerAccessToken(
|
|
342
|
-
undefined,
|
|
343
|
-
1000 * 60 * 10, // 10 minutes
|
|
344
|
-
tokenInfo
|
|
345
|
-
);
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Build entity metadata for Skip
|
|
355
|
+
* Copied from AskSkipResolver.BuildSkipEntities - uses cached metadata with refresh logic
|
|
356
|
+
*/
|
|
357
|
+
private async buildEntities(dataSource: mssql.ConnectionPool, forceRefresh: boolean, refreshIntervalMinutes: number = 15): Promise<SkipEntityInfo[]> {
|
|
358
|
+
try {
|
|
359
|
+
const now = Date.now();
|
|
360
|
+
const cacheExpired = (now - SkipSDK.__lastRefreshTime) > (refreshIntervalMinutes * 60 * 1000);
|
|
361
|
+
|
|
362
|
+
// If force refresh is requested OR cache expired OR cache is empty, refresh
|
|
363
|
+
if (forceRefresh || cacheExpired || SkipSDK.__skipEntitiesCache$.value === null) {
|
|
364
|
+
LogStatus(`[SkipSDK] Refreshing Skip entities cache (force: ${forceRefresh}, expired: ${cacheExpired})`);
|
|
365
|
+
const newData = this.refreshSkipEntities(dataSource);
|
|
366
|
+
SkipSDK.__skipEntitiesCache$.next(newData);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return SkipSDK.__skipEntitiesCache$.pipe(take(1)).toPromise();
|
|
370
|
+
}
|
|
371
|
+
catch (e) {
|
|
372
|
+
LogError(`[SkipSDK] buildEntities error: ${e}`);
|
|
373
|
+
return [];
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Build saved queries for Skip
|
|
379
|
+
*/
|
|
380
|
+
private buildQueries(status: "Pending" | "In-Review" | "Approved" | "Rejected" | "Obsolete" = 'Approved'): SkipQueryInfo[] {
|
|
381
|
+
const md = new Metadata();
|
|
382
|
+
const approvedQueries = md.Queries.filter((q) => q.Status === status);
|
|
383
|
+
|
|
384
|
+
return approvedQueries.map((q) => ({
|
|
385
|
+
id: q.ID,
|
|
386
|
+
name: q.Name,
|
|
387
|
+
description: q.Description,
|
|
388
|
+
category: q.Category,
|
|
389
|
+
categoryPath: this.buildQueryCategoryPath(md, q.CategoryID),
|
|
390
|
+
sql: q.SQL,
|
|
391
|
+
originalSQL: q.OriginalSQL,
|
|
392
|
+
feedback: q.Feedback,
|
|
393
|
+
status: q.Status,
|
|
394
|
+
qualityRank: q.QualityRank,
|
|
395
|
+
createdAt: q.__mj_CreatedAt,
|
|
396
|
+
updatedAt: q.__mj_UpdatedAt,
|
|
397
|
+
categoryID: q.CategoryID,
|
|
398
|
+
embeddingVector: q.EmbeddingVector,
|
|
399
|
+
embeddingModelID: q.EmbeddingModelID,
|
|
400
|
+
embeddingModelName: q.EmbeddingModel,
|
|
401
|
+
fields: q.Fields.map((f) => ({
|
|
402
|
+
id: f.ID,
|
|
403
|
+
queryID: f.QueryID,
|
|
404
|
+
sequence: f.Sequence,
|
|
405
|
+
name: f.Name,
|
|
406
|
+
description: f.Description,
|
|
407
|
+
sqlBaseType: f.SQLBaseType,
|
|
408
|
+
sqlFullType: f.SQLFullType,
|
|
409
|
+
sourceEntityID: f.SourceEntityID,
|
|
410
|
+
sourceEntity: f.SourceEntity,
|
|
411
|
+
sourceFieldName: f.SourceFieldName,
|
|
412
|
+
isComputed: f.IsComputed,
|
|
413
|
+
computationDescription: f.ComputationDescription,
|
|
414
|
+
isSummary: f.IsSummary,
|
|
415
|
+
summaryDescription: f.SummaryDescription,
|
|
416
|
+
createdAt: f.__mj_CreatedAt,
|
|
417
|
+
updatedAt: f.__mj_UpdatedAt
|
|
418
|
+
})),
|
|
419
|
+
params: q.Parameters.map((p) => ({
|
|
420
|
+
id: p.ID,
|
|
421
|
+
queryID: p.QueryID,
|
|
422
|
+
name: p.Name,
|
|
423
|
+
description: p.Description,
|
|
424
|
+
type: p.Type,
|
|
425
|
+
isRequired: p.IsRequired,
|
|
426
|
+
// LinkedParameterName and LinkedParameterType may not exist on QueryParameterInfo
|
|
427
|
+
defaultValue: p.DefaultValue,
|
|
428
|
+
createdAt: p.__mj_CreatedAt,
|
|
429
|
+
updatedAt: p.__mj_UpdatedAt
|
|
430
|
+
}))
|
|
431
|
+
}));
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Recursively build category path for a query
|
|
436
|
+
*/
|
|
437
|
+
private buildQueryCategoryPath(md: Metadata, categoryID: string): string {
|
|
438
|
+
const cat = md.QueryCategories.find((c) => c.ID === categoryID);
|
|
439
|
+
if (!cat) return '';
|
|
440
|
+
if (!cat.ParentID) return cat.Name;
|
|
441
|
+
const parentPath = this.buildQueryCategoryPath(md, cat.ParentID);
|
|
442
|
+
return parentPath ? `${parentPath}/${cat.Name}` : cat.Name;
|
|
346
443
|
}
|
|
347
444
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
apiKeys: this.buildAPIKeys(),
|
|
357
|
-
callingServerURL: accessToken ? publicUrl || `${baseUrl}:${graphqlPort}${graphqlRootPath}` : undefined,
|
|
358
|
-
callingServerAPIKey: accessToken ? callbackAPIKey : undefined,
|
|
359
|
-
callingServerAccessToken: accessToken ? accessToken.Token : undefined,
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Build entity metadata for Skip
|
|
365
|
-
* Copied from AskSkipResolver.BuildSkipEntities - uses cached metadata with refresh logic
|
|
366
|
-
*/
|
|
367
|
-
private async buildEntities(
|
|
368
|
-
dataSource: mssql.ConnectionPool,
|
|
369
|
-
forceRefresh: boolean,
|
|
370
|
-
refreshIntervalMinutes: number = 15
|
|
371
|
-
): Promise<SkipEntityInfo[]> {
|
|
372
|
-
try {
|
|
373
|
-
const now = Date.now();
|
|
374
|
-
const cacheExpired = now - SkipSDK.__lastRefreshTime > refreshIntervalMinutes * 60 * 1000;
|
|
375
|
-
|
|
376
|
-
// If force refresh is requested OR cache expired OR cache is empty, refresh
|
|
377
|
-
if (forceRefresh || cacheExpired || SkipSDK.__skipEntitiesCache$.value === null) {
|
|
378
|
-
LogStatus(`[SkipSDK] Refreshing Skip entities cache (force: ${forceRefresh}, expired: ${cacheExpired})`);
|
|
379
|
-
const newData = this.refreshSkipEntities(dataSource);
|
|
380
|
-
SkipSDK.__skipEntitiesCache$.next(newData);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return SkipSDK.__skipEntitiesCache$.pipe(take(1)).toPromise();
|
|
384
|
-
} catch (e) {
|
|
385
|
-
LogError(`[SkipSDK] buildEntities error: ${e}`);
|
|
386
|
-
return [];
|
|
445
|
+
/**
|
|
446
|
+
* Build agent notes for Skip
|
|
447
|
+
*/
|
|
448
|
+
private async buildAgentNotes(contextUser: UserInfo): Promise<{ notes: SkipAPIAgentNote[], noteTypes: SkipAPIAgentNoteType[] }> {
|
|
449
|
+
// TODO: Implement agent notes building
|
|
450
|
+
// This would query AIAgentNote entities and convert to SkipAPIAgentNote format
|
|
451
|
+
// For now, returning empty arrays
|
|
452
|
+
return { notes: [], noteTypes: [] };
|
|
387
453
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
ConversationID: conversationId,
|
|
499
|
-
AgentID: skipAgentId, // Filter to only artifacts created by Skip agent
|
|
500
|
-
},
|
|
501
|
-
},
|
|
502
|
-
contextUser
|
|
503
|
-
);
|
|
504
|
-
|
|
505
|
-
if (!result.Success || !result.Results || result.Results.length === 0) {
|
|
506
|
-
return [];
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
// Query returns flat result set: one row per artifact version
|
|
510
|
-
// Group by ArtifactID to build SkipAPIArtifact objects with their versions
|
|
511
|
-
const artifactMap = new Map<
|
|
512
|
-
string,
|
|
513
|
-
{
|
|
514
|
-
artifact: any;
|
|
515
|
-
artifactType: SkipAPIArtifactType;
|
|
516
|
-
versions: SkipAPIArtifactVersion[];
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Build artifacts for a conversation using optimized query
|
|
457
|
+
* Uses GetConversationArtifactsForAgent query which joins through ConversationDetailArtifact
|
|
458
|
+
* to get artifacts that were outputs from Skip agent's conversation details
|
|
459
|
+
*/
|
|
460
|
+
private async buildArtifacts(contextUser: UserInfo, dataSource: mssql.ConnectionPool, conversationId: string): Promise<SkipAPIArtifact[]> {
|
|
461
|
+
try {
|
|
462
|
+
const rq = new RunQuery();
|
|
463
|
+
|
|
464
|
+
// Ensure AIEngine is configured and get Skip agent ID
|
|
465
|
+
await AIEngine.Instance.Config(false, contextUser);
|
|
466
|
+
const skipAgent = AIEngine.Instance.GetAgentByName('Skip');
|
|
467
|
+
const skipAgentId = skipAgent?.ID;
|
|
468
|
+
|
|
469
|
+
if (!skipAgentId) {
|
|
470
|
+
LogError('[SkipSDK] Skip agent not found in AIEngine');
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Use optimized query that replaces 4 RunView calls with 1 query
|
|
474
|
+
// This query includes Configuration field needed for component spec extraction
|
|
475
|
+
// Filter by Skip agent ID to only get artifacts created by Skip (not delegation agents)
|
|
476
|
+
const result = await rq.RunQuery({
|
|
477
|
+
QueryName: 'GetConversationArtifactsForAgent',
|
|
478
|
+
CategoryPath: 'MJ/Conversations',
|
|
479
|
+
Parameters: {
|
|
480
|
+
ConversationID: conversationId,
|
|
481
|
+
AgentID: skipAgentId // Filter to only artifacts created by Skip agent
|
|
482
|
+
}
|
|
483
|
+
}, contextUser);
|
|
484
|
+
|
|
485
|
+
if (!result.Success || !result.Results || result.Results.length === 0) {
|
|
486
|
+
return [];
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Query returns flat result set: one row per artifact version
|
|
490
|
+
// Group by ArtifactID to build SkipAPIArtifact objects with their versions
|
|
491
|
+
const artifactMap = new Map<string, {
|
|
492
|
+
artifact: any,
|
|
493
|
+
artifactType: SkipAPIArtifactType,
|
|
494
|
+
versions: SkipAPIArtifactVersion[]
|
|
495
|
+
}>();
|
|
496
|
+
|
|
497
|
+
// Process each row (represents one version)
|
|
498
|
+
for (const row of result.Results) {
|
|
499
|
+
const artifactId = row.ArtifactID;
|
|
500
|
+
|
|
501
|
+
// Initialize artifact entry if not exists
|
|
502
|
+
if (!artifactMap.has(artifactId)) {
|
|
503
|
+
// Map database sharingScope values to SkipAPIArtifact expected values
|
|
504
|
+
let sharingScope: 'None' | 'SpecificUsers' | 'Everyone' | 'Public' = 'None';
|
|
505
|
+
const dbSharingScope = (row.SharingScope || '').toLowerCase();
|
|
506
|
+
if (dbSharingScope === 'always' || dbSharingScope === 'everyone') {
|
|
507
|
+
sharingScope = 'Everyone';
|
|
508
|
+
} else if (dbSharingScope === 'public') {
|
|
509
|
+
sharingScope = 'Public';
|
|
510
|
+
} else if (dbSharingScope === 'specific users' || dbSharingScope === 'specificusers') {
|
|
511
|
+
sharingScope = 'SpecificUsers';
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
artifactMap.set(artifactId, {
|
|
515
|
+
artifact: {
|
|
516
|
+
id: artifactId,
|
|
517
|
+
conversationId: conversationId,
|
|
518
|
+
name: row.ArtifactName,
|
|
519
|
+
description: row.ArtifactDescription || '',
|
|
520
|
+
sharingScope: sharingScope,
|
|
521
|
+
comments: row.ArtifactComments || '',
|
|
522
|
+
createdAt: new Date(row.ArtifactCreatedAt),
|
|
523
|
+
updatedAt: new Date(row.ArtifactUpdatedAt)
|
|
524
|
+
},
|
|
525
|
+
artifactType: {
|
|
526
|
+
id: row.ArtifactTypeID,
|
|
527
|
+
name: row.ArtifactTypeName,
|
|
528
|
+
description: row.ArtifactTypeDescription,
|
|
529
|
+
contentType: row.ArtifactTypeContentType,
|
|
530
|
+
enabled: true,
|
|
531
|
+
createdAt: new Date(row.ArtifactTypeCreatedAt),
|
|
532
|
+
updatedAt: new Date(row.ArtifactTypeUpdatedAt)
|
|
533
|
+
},
|
|
534
|
+
versions: []
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Add this version to the artifact
|
|
539
|
+
const entry = artifactMap.get(artifactId)!;
|
|
540
|
+
entry.versions.push({
|
|
541
|
+
id: row.VersionID,
|
|
542
|
+
artifactId: artifactId,
|
|
543
|
+
conversationDetailID: row.ConversationDetailID, // Direct from join table!
|
|
544
|
+
version: row.Version,
|
|
545
|
+
configuration: row.Configuration || '',
|
|
546
|
+
content: row.Content || '',
|
|
547
|
+
comments: row.VersionComments || '',
|
|
548
|
+
createdAt: new Date(row.VersionCreatedAt),
|
|
549
|
+
updatedAt: new Date(row.VersionUpdatedAt)
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Convert map to SkipAPIArtifact array
|
|
554
|
+
const artifacts: SkipAPIArtifact[] = Array.from(artifactMap.values()).map(entry => ({
|
|
555
|
+
...entry.artifact,
|
|
556
|
+
artifactType: entry.artifactType,
|
|
557
|
+
versions: entry.versions
|
|
558
|
+
}));
|
|
559
|
+
|
|
560
|
+
return artifacts;
|
|
561
|
+
} catch (error) {
|
|
562
|
+
LogError(`Failed to build artifacts for conversation ${conversationId}: ${error}`);
|
|
563
|
+
return [];
|
|
517
564
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const dbSharingScope = (row.SharingScope || '').toLowerCase();
|
|
529
|
-
if (dbSharingScope === 'always' || dbSharingScope === 'everyone') {
|
|
530
|
-
sharingScope = 'Everyone';
|
|
531
|
-
} else if (dbSharingScope === 'public') {
|
|
532
|
-
sharingScope = 'Public';
|
|
533
|
-
} else if (dbSharingScope === 'specific users' || dbSharingScope === 'specificusers') {
|
|
534
|
-
sharingScope = 'SpecificUsers';
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
artifactMap.set(artifactId, {
|
|
538
|
-
artifact: {
|
|
539
|
-
id: artifactId,
|
|
540
|
-
conversationId: conversationId,
|
|
541
|
-
name: row.ArtifactName,
|
|
542
|
-
description: row.ArtifactDescription || '',
|
|
543
|
-
sharingScope: sharingScope,
|
|
544
|
-
comments: row.ArtifactComments || '',
|
|
545
|
-
createdAt: new Date(row.ArtifactCreatedAt),
|
|
546
|
-
updatedAt: new Date(row.ArtifactUpdatedAt),
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Build API keys for AI services
|
|
569
|
+
*/
|
|
570
|
+
private buildAPIKeys(): SkipAPIRequestAPIKey[] {
|
|
571
|
+
return [
|
|
572
|
+
{
|
|
573
|
+
vendorDriverName: 'OpenAILLM',
|
|
574
|
+
apiKey: GetAIAPIKey('OpenAILLM')
|
|
547
575
|
},
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
description: row.ArtifactTypeDescription,
|
|
552
|
-
contentType: row.ArtifactTypeContentType,
|
|
553
|
-
enabled: true,
|
|
554
|
-
createdAt: new Date(row.ArtifactTypeCreatedAt),
|
|
555
|
-
updatedAt: new Date(row.ArtifactTypeUpdatedAt),
|
|
576
|
+
{
|
|
577
|
+
vendorDriverName: 'AnthropicLLM',
|
|
578
|
+
apiKey: GetAIAPIKey('AnthropicLLM')
|
|
556
579
|
},
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
580
|
+
{
|
|
581
|
+
vendorDriverName: 'GeminiLLM',
|
|
582
|
+
apiKey: GetAIAPIKey('GeminiLLM')
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
vendorDriverName: 'GroqLLM',
|
|
586
|
+
apiKey: GetAIAPIKey('GroqLLM')
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
vendorDriverName: 'MistralLLM',
|
|
590
|
+
apiKey: GetAIAPIKey('MistralLLM')
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
vendorDriverName: 'CerebrasLLM',
|
|
594
|
+
apiKey: GetAIAPIKey('CerebrasLLM')
|
|
595
|
+
}
|
|
596
|
+
];
|
|
597
|
+
}
|
|
560
598
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
content: row.Content || '',
|
|
570
|
-
comments: row.VersionComments || '',
|
|
571
|
-
createdAt: new Date(row.VersionCreatedAt),
|
|
572
|
-
updatedAt: new Date(row.VersionUpdatedAt),
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// Convert map to SkipAPIArtifact array
|
|
577
|
-
const artifacts: SkipAPIArtifact[] = Array.from(artifactMap.values()).map((entry) => ({
|
|
578
|
-
...entry.artifact,
|
|
579
|
-
artifactType: entry.artifactType,
|
|
580
|
-
versions: entry.versions,
|
|
581
|
-
}));
|
|
582
|
-
|
|
583
|
-
return artifacts;
|
|
584
|
-
} catch (error) {
|
|
585
|
-
LogError(`Failed to build artifacts for conversation ${conversationId}: ${error}`);
|
|
586
|
-
return [];
|
|
599
|
+
/**
|
|
600
|
+
* Build HTTP headers for Skip API requests
|
|
601
|
+
*/
|
|
602
|
+
private buildHeaders(): Record<string, string> {
|
|
603
|
+
return {
|
|
604
|
+
'x-api-key': this.config.apiKey || '',
|
|
605
|
+
'Content-Type': 'application/json'
|
|
606
|
+
};
|
|
587
607
|
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* Build API keys for AI services
|
|
592
|
-
*/
|
|
593
|
-
private buildAPIKeys(): SkipAPIRequestAPIKey[] {
|
|
594
|
-
return [
|
|
595
|
-
{
|
|
596
|
-
vendorDriverName: 'OpenAILLM',
|
|
597
|
-
apiKey: GetAIAPIKey('OpenAILLM'),
|
|
598
|
-
},
|
|
599
|
-
{
|
|
600
|
-
vendorDriverName: 'AnthropicLLM',
|
|
601
|
-
apiKey: GetAIAPIKey('AnthropicLLM'),
|
|
602
|
-
},
|
|
603
|
-
{
|
|
604
|
-
vendorDriverName: 'GeminiLLM',
|
|
605
|
-
apiKey: GetAIAPIKey('GeminiLLM'),
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
vendorDriverName: 'GroqLLM',
|
|
609
|
-
apiKey: GetAIAPIKey('GroqLLM'),
|
|
610
|
-
},
|
|
611
|
-
{
|
|
612
|
-
vendorDriverName: 'MistralLLM',
|
|
613
|
-
apiKey: GetAIAPIKey('MistralLLM'),
|
|
614
|
-
},
|
|
615
|
-
{
|
|
616
|
-
vendorDriverName: 'CerebrasLLM',
|
|
617
|
-
apiKey: GetAIAPIKey('CerebrasLLM'),
|
|
618
|
-
},
|
|
619
|
-
];
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
/**
|
|
623
|
-
* Build HTTP headers for Skip API requests
|
|
624
|
-
*/
|
|
625
|
-
private buildHeaders(): Record<string, string> {
|
|
626
|
-
return {
|
|
627
|
-
'x-api-key': this.config.apiKey || '',
|
|
628
|
-
'Content-Type': 'application/json',
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Refreshes the Skip entities cache
|
|
634
|
-
* Rebuilds the entity information that is provided to Skip
|
|
635
|
-
* Copied from AskSkipResolver.refreshSkipEntities
|
|
636
|
-
*/
|
|
637
|
-
private async refreshSkipEntities(dataSource: mssql.ConnectionPool): Promise<SkipEntityInfo[]> {
|
|
638
|
-
try {
|
|
639
|
-
const md = new Metadata();
|
|
640
|
-
const skipSpecialIncludeEntities = (configInfo.askSkip?.entitiesToSend?.includeEntitiesFromExcludedSchemas ?? []).map((e) =>
|
|
641
|
-
e.trim().toLowerCase()
|
|
642
|
-
);
|
|
643
|
-
|
|
644
|
-
// Get the list of entities
|
|
645
|
-
const entities = md.Entities.filter((e) => {
|
|
646
|
-
if (
|
|
647
|
-
!configInfo.askSkip.entitiesToSend.excludeSchemas.includes(e.SchemaName) ||
|
|
648
|
-
skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase())
|
|
649
|
-
) {
|
|
650
|
-
const sd = e.ScopeDefault?.trim();
|
|
651
|
-
if (sd && sd.length > 0) {
|
|
652
|
-
const scopes = sd.split(',').map((s) => s.trim().toLowerCase()) ?? ['all'];
|
|
653
|
-
return (
|
|
654
|
-
!scopes ||
|
|
655
|
-
scopes.length === 0 ||
|
|
656
|
-
scopes.includes('all') ||
|
|
657
|
-
scopes.includes('ai') ||
|
|
658
|
-
skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase())
|
|
659
|
-
);
|
|
660
|
-
} else {
|
|
661
|
-
return true; // no scope, so include it
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
return false;
|
|
665
|
-
});
|
|
666
608
|
|
|
667
|
-
|
|
668
|
-
|
|
609
|
+
/**
|
|
610
|
+
* Refreshes the Skip entities cache
|
|
611
|
+
* Rebuilds the entity information that is provided to Skip
|
|
612
|
+
* Copied from AskSkipResolver.refreshSkipEntities
|
|
613
|
+
*/
|
|
614
|
+
private async refreshSkipEntities(dataSource: mssql.ConnectionPool): Promise<SkipEntityInfo[]> {
|
|
615
|
+
try {
|
|
616
|
+
const md = new Metadata();
|
|
617
|
+
const skipSpecialIncludeEntities = (configInfo.askSkip?.entitiesToSend?.includeEntitiesFromExcludedSchemas ?? [])
|
|
618
|
+
.map((e) => e.trim().toLowerCase());
|
|
619
|
+
|
|
620
|
+
// Get the list of entities
|
|
621
|
+
const entities = md.Entities.filter((e) => {
|
|
622
|
+
if (!configInfo.askSkip.entitiesToSend.excludeSchemas.includes(e.SchemaName) ||
|
|
623
|
+
skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase())) {
|
|
624
|
+
const sd = e.ScopeDefault?.trim();
|
|
625
|
+
if (sd && sd.length > 0) {
|
|
626
|
+
const scopes = sd.split(',').map((s) => s.trim().toLowerCase()) ?? ['all'];
|
|
627
|
+
return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai') || skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase());
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
return true; // no scope, so include it
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
return false;
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
// Now we have our list of entities, pack em up
|
|
637
|
+
const result = await Promise.all(entities.map((e) => this.packSingleSkipEntityInfo(e, dataSource)));
|
|
669
638
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
639
|
+
SkipSDK.__lastRefreshTime = Date.now(); // Update last refresh time
|
|
640
|
+
return result;
|
|
641
|
+
}
|
|
642
|
+
catch (e) {
|
|
643
|
+
LogError(`[SkipSDK] refreshSkipEntities error: ${e}`);
|
|
644
|
+
return [];
|
|
645
|
+
}
|
|
675
646
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
return null;
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Packs information about a single entity for Skip
|
|
650
|
+
* Includes fields, relationships, and sample data
|
|
651
|
+
* Copied from AskSkipResolver.PackSingleSkipEntityInfo
|
|
652
|
+
*/
|
|
653
|
+
private async packSingleSkipEntityInfo(e: EntityInfo, dataSource: mssql.ConnectionPool): Promise<SkipEntityInfo> {
|
|
654
|
+
try {
|
|
655
|
+
const ret: SkipEntityInfo = {
|
|
656
|
+
id: e.ID,
|
|
657
|
+
name: e.Name,
|
|
658
|
+
schemaName: e.SchemaName,
|
|
659
|
+
baseView: e.BaseView,
|
|
660
|
+
description: e.Description,
|
|
661
|
+
|
|
662
|
+
fields: await Promise.all(e.Fields.filter(f => {
|
|
663
|
+
// we want to check the scopes for the field level and make sure it is either All or AI or has both
|
|
664
|
+
const scopes = f.ScopeDefault?.split(',').map((s) => s.trim().toLowerCase());
|
|
665
|
+
return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai');
|
|
666
|
+
}).map(f => {
|
|
667
|
+
return this.packSingleSkipEntityField(f, dataSource);
|
|
668
|
+
})),
|
|
669
|
+
|
|
670
|
+
relatedEntities: e.RelatedEntities.map((r) => {
|
|
671
|
+
return this.packSingleSkipEntityRelationship(r);
|
|
672
|
+
}),
|
|
673
|
+
|
|
674
|
+
rowsPacked: e.RowsToPackWithSchema,
|
|
675
|
+
rowsSampleMethod: e.RowsToPackSampleMethod,
|
|
676
|
+
rows: await this.packEntityRows(e, dataSource)
|
|
677
|
+
};
|
|
678
|
+
return ret;
|
|
679
|
+
}
|
|
680
|
+
catch (e) {
|
|
681
|
+
LogError(`[SkipSDK] packSingleSkipEntityInfo error: ${e}`);
|
|
682
|
+
return null;
|
|
683
|
+
}
|
|
714
684
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Packs information about a single entity relationship
|
|
688
|
+
* These relationships help Skip understand the data model
|
|
689
|
+
* Copied from AskSkipResolver.PackSingleSkipEntityRelationship
|
|
690
|
+
*/
|
|
691
|
+
private packSingleSkipEntityRelationship(r: EntityRelationshipInfo): SkipEntityRelationshipInfo {
|
|
692
|
+
try {
|
|
693
|
+
return {
|
|
694
|
+
entityID: r.EntityID,
|
|
695
|
+
relatedEntityID: r.RelatedEntityID,
|
|
696
|
+
type: r.Type,
|
|
697
|
+
entityKeyField: r.EntityKeyField,
|
|
698
|
+
relatedEntityJoinField: r.RelatedEntityJoinField,
|
|
699
|
+
joinView: r.JoinView,
|
|
700
|
+
joinEntityJoinField: r.JoinEntityJoinField,
|
|
701
|
+
joinEntityInverseJoinField: r.JoinEntityInverseJoinField,
|
|
702
|
+
entity: r.Entity,
|
|
703
|
+
entityBaseView: r.EntityBaseView,
|
|
704
|
+
relatedEntity: r.RelatedEntity,
|
|
705
|
+
relatedEntityBaseView: r.RelatedEntityBaseView,
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
catch (e) {
|
|
709
|
+
LogError(`[SkipSDK] packSingleSkipEntityRelationship error: ${e}`);
|
|
710
|
+
return null;
|
|
711
|
+
}
|
|
741
712
|
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Packs information about a single entity field
|
|
716
|
+
* Includes metadata and possible values
|
|
717
|
+
* Copied from AskSkipResolver.PackSingleSkipEntityField
|
|
718
|
+
*/
|
|
719
|
+
private async packSingleSkipEntityField(f: EntityFieldInfo, dataSource: mssql.ConnectionPool): Promise<SkipEntityFieldInfo> {
|
|
720
|
+
try {
|
|
721
|
+
return {
|
|
722
|
+
entityID: f.EntityID,
|
|
723
|
+
sequence: f.Sequence,
|
|
724
|
+
name: f.Name,
|
|
725
|
+
displayName: f.DisplayName,
|
|
726
|
+
category: f.Category,
|
|
727
|
+
type: f.Type,
|
|
728
|
+
description: f.Description,
|
|
729
|
+
isPrimaryKey: f.IsPrimaryKey,
|
|
730
|
+
allowsNull: f.AllowsNull,
|
|
731
|
+
isUnique: f.IsUnique,
|
|
732
|
+
length: f.Length,
|
|
733
|
+
precision: f.Precision,
|
|
734
|
+
scale: f.Scale,
|
|
735
|
+
sqlFullType: f.SQLFullType,
|
|
736
|
+
defaultValue: f.DefaultValue,
|
|
737
|
+
autoIncrement: f.AutoIncrement,
|
|
738
|
+
valueListType: f.ValueListType,
|
|
739
|
+
extendedType: f.ExtendedType,
|
|
740
|
+
defaultInView: f.DefaultInView,
|
|
741
|
+
defaultColumnWidth: f.DefaultColumnWidth,
|
|
742
|
+
isVirtual: f.IsVirtual,
|
|
743
|
+
isNameField: f.IsNameField,
|
|
744
|
+
relatedEntityID: f.RelatedEntityID,
|
|
745
|
+
relatedEntityFieldName: f.RelatedEntityFieldName,
|
|
746
|
+
relatedEntity: f.RelatedEntity,
|
|
747
|
+
relatedEntitySchemaName: f.RelatedEntitySchemaName,
|
|
748
|
+
relatedEntityBaseView: f.RelatedEntityBaseView,
|
|
749
|
+
possibleValues: await this.packFieldPossibleValues(f, dataSource),
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
catch (e) {
|
|
753
|
+
LogError(`[SkipSDK] packSingleSkipEntityField error: ${e}`);
|
|
754
|
+
return null;
|
|
755
|
+
}
|
|
784
756
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
const innerOrderBy = e.RowsToPackSampleOrder ? `[${e.RowsToPackSampleOrder}]` : `[${firstPrimaryKey}] DESC`;
|
|
821
|
-
sql = `SELECT * FROM (
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Packs entity rows (sample data)
|
|
760
|
+
* Copied from AskSkipResolver.PackEntityRows
|
|
761
|
+
*/
|
|
762
|
+
private async packEntityRows(e: EntityInfo, dataSource: mssql.ConnectionPool): Promise<any[]> {
|
|
763
|
+
try {
|
|
764
|
+
if (e.RowsToPackWithSchema === 'None')
|
|
765
|
+
return [];
|
|
766
|
+
|
|
767
|
+
// only include columns that have a scopes including either All and/or AI or have Null for ScopeDefault
|
|
768
|
+
const fields = e.Fields.filter((f) => {
|
|
769
|
+
const scopes = f.ScopeDefault?.split(',').map((s) => s.trim().toLowerCase());
|
|
770
|
+
return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai');
|
|
771
|
+
}).map(f => `[${f.Name}]`).join(',');
|
|
772
|
+
|
|
773
|
+
// now run the query based on the row packing method
|
|
774
|
+
let sql: string = '';
|
|
775
|
+
switch (e.RowsToPackWithSchema) {
|
|
776
|
+
case 'All':
|
|
777
|
+
sql = `SELECT ${fields} FROM ${e.SchemaName}.${e.BaseView}`;
|
|
778
|
+
break;
|
|
779
|
+
case 'Sample':
|
|
780
|
+
switch (e.RowsToPackSampleMethod) {
|
|
781
|
+
case 'random':
|
|
782
|
+
sql = `SELECT TOP ${e.RowsToPackSampleCount} ${fields} FROM [${e.SchemaName}].[${e.BaseView}] ORDER BY newid()`;
|
|
783
|
+
break;
|
|
784
|
+
case 'top n':
|
|
785
|
+
const orderBy = e.RowsToPackSampleOrder ? ` ORDER BY [${e.RowsToPackSampleOrder}]` : '';
|
|
786
|
+
sql = `SELECT TOP ${e.RowsToPackSampleCount} ${fields} FROM [${e.SchemaName}].[${e.BaseView}]${orderBy}`;
|
|
787
|
+
break;
|
|
788
|
+
case 'bottom n':
|
|
789
|
+
const firstPrimaryKey = e.FirstPrimaryKey.Name;
|
|
790
|
+
const innerOrderBy = e.RowsToPackSampleOrder ? `[${e.RowsToPackSampleOrder}]` : `[${firstPrimaryKey}] DESC`;
|
|
791
|
+
sql = `SELECT * FROM (
|
|
822
792
|
SELECT TOP ${e.RowsToPackSampleCount} ${fields}
|
|
823
793
|
FROM [${e.SchemaName}].[${e.BaseView}]
|
|
824
794
|
ORDER BY ${innerOrderBy}
|
|
825
795
|
) sub
|
|
826
796
|
ORDER BY [${firstPrimaryKey}] ASC;`;
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
const request = new mssql.Request(dataSource);
|
|
801
|
+
const result = await request.query(sql);
|
|
802
|
+
if (!result || !result.recordset) {
|
|
803
|
+
return [];
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
return result.recordset;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
catch (e) {
|
|
810
|
+
LogError(`[SkipSDK] packEntityRows error: ${e}`);
|
|
811
|
+
return [];
|
|
812
|
+
}
|
|
840
813
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Packs possible values for an entity field
|
|
817
|
+
* These values help Skip understand the domain and valid values for fields
|
|
818
|
+
* Copied from AskSkipResolver.PackFieldPossibleValues
|
|
819
|
+
*/
|
|
820
|
+
private async packFieldPossibleValues(f: EntityFieldInfo, dataSource: mssql.ConnectionPool): Promise<SkipEntityFieldValueInfo[]> {
|
|
821
|
+
try {
|
|
822
|
+
if (f.ValuesToPackWithSchema === 'None') {
|
|
823
|
+
return []; // don't pack anything
|
|
824
|
+
}
|
|
825
|
+
else if (f.ValuesToPackWithSchema === 'All') {
|
|
826
|
+
// wants ALL of the distinct values
|
|
827
|
+
return await this.getFieldDistinctValues(f, dataSource);
|
|
828
|
+
}
|
|
829
|
+
else if (f.ValuesToPackWithSchema === 'Auto') {
|
|
830
|
+
// default setting - pack based on the ValueListType
|
|
831
|
+
if (f.ValueListTypeEnum === 'List') {
|
|
832
|
+
// simple list of values in the Entity Field Values table
|
|
833
|
+
return f.EntityFieldValues.map((v) => {
|
|
834
|
+
return { value: v.Value, displayValue: v.Value };
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
else if (f.ValueListTypeEnum === 'ListOrUserEntry') {
|
|
838
|
+
// could be a user provided value, OR the values in the list of possible values.
|
|
839
|
+
// get the distinct list of values from the DB and concat that with the f.EntityFieldValues array - deduped and return
|
|
840
|
+
const values = await this.getFieldDistinctValues(f, dataSource);
|
|
841
|
+
if (!values || values.length === 0) {
|
|
842
|
+
// no result, just return the EntityFieldValues
|
|
843
|
+
return f.EntityFieldValues.map((v) => {
|
|
844
|
+
return { value: v.Value, displayValue: v.Value };
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
return [...new Set([...f.EntityFieldValues.map((v) => {
|
|
849
|
+
return { value: v.Value, displayValue: v.Value };
|
|
850
|
+
}), ...values])];
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return []; // if we get here, nothing to pack
|
|
855
|
+
}
|
|
856
|
+
catch (e) {
|
|
857
|
+
LogError(`[SkipSDK] packFieldPossibleValues error: ${e}`);
|
|
858
|
+
return [];
|
|
881
859
|
}
|
|
882
|
-
}
|
|
883
|
-
return []; // if we get here, nothing to pack
|
|
884
|
-
} catch (e) {
|
|
885
|
-
LogError(`[SkipSDK] packFieldPossibleValues error: ${e}`);
|
|
886
|
-
return [];
|
|
887
860
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Gets distinct values for a field from the database
|
|
864
|
+
* Used to provide Skip with information about the possible values
|
|
865
|
+
* Copied from AskSkipResolver.GetFieldDistinctValues
|
|
866
|
+
*/
|
|
867
|
+
private async getFieldDistinctValues(f: EntityFieldInfo, dataSource: mssql.ConnectionPool): Promise<SkipEntityFieldValueInfo[]> {
|
|
868
|
+
try {
|
|
869
|
+
const sql = `SELECT DISTINCT ${f.Name} FROM ${f.SchemaName}.${f.BaseView}`;
|
|
870
|
+
const request = new mssql.Request(dataSource);
|
|
871
|
+
const result = await request.query(sql);
|
|
872
|
+
if (!result || !result.recordset) {
|
|
873
|
+
return [];
|
|
874
|
+
}
|
|
875
|
+
else {
|
|
876
|
+
return result.recordset.map((r) => {
|
|
877
|
+
return {
|
|
878
|
+
value: r[f.Name],
|
|
879
|
+
displayValue: r[f.Name]
|
|
880
|
+
};
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
catch (e) {
|
|
885
|
+
LogError(`[SkipSDK] getFieldDistinctValues error: ${e}`);
|
|
886
|
+
return [];
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Process messages: filter delegation messages and add metadata fields
|
|
892
|
+
* Messages coming in should already have conversationDetailID if they exist in the database
|
|
893
|
+
*/
|
|
894
|
+
private processMessages(messages: SkipMessage[]): SkipMessage[] {
|
|
895
|
+
// Filter out delegation messages (administrative messages that shouldn't go to Skip)
|
|
896
|
+
const filteredMessages = messages.filter(msg => !this.isDelegationMessage(msg.content));
|
|
897
|
+
|
|
898
|
+
// Enrich messages with default metadata if not already present
|
|
899
|
+
return filteredMessages.map(msg => ({
|
|
900
|
+
...msg,
|
|
901
|
+
// Add default metadata fields if not already present
|
|
902
|
+
// Messages from DB already have conversationDetailID, temp messages get temp-X
|
|
903
|
+
hiddenToUser: msg.hiddenToUser ?? false,
|
|
904
|
+
userRating: msg.userRating ?? null,
|
|
905
|
+
userFeedback: msg.userFeedback ?? null,
|
|
906
|
+
reflectionInsights: msg.reflectionInsights ?? null,
|
|
907
|
+
summaryOfEarlierConveration: msg.summaryOfEarlierConveration ?? null
|
|
908
|
+
}));
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Check if a message is a delegation message that should be filtered out
|
|
913
|
+
* Uses flexible pattern matching to detect variations of delegation messages
|
|
914
|
+
*/
|
|
915
|
+
private isDelegationMessage(content: string): boolean {
|
|
916
|
+
if (!content) return false;
|
|
917
|
+
|
|
918
|
+
const lowerContent = content.toLowerCase();
|
|
919
|
+
|
|
920
|
+
// Check for both "delegating" or "delegate" AND "skip" in any order
|
|
921
|
+
const hasDelegatingOrDelegate = lowerContent.includes('delegating') || lowerContent.includes('delegate');
|
|
922
|
+
const hasSkip = lowerContent.includes('skip');
|
|
923
|
+
|
|
924
|
+
return hasDelegatingOrDelegate && hasSkip;
|
|
913
925
|
}
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
/**
|
|
917
|
-
* Process messages: filter delegation messages and add metadata fields
|
|
918
|
-
* Messages coming in should already have conversationDetailID if they exist in the database
|
|
919
|
-
*/
|
|
920
|
-
private processMessages(messages: SkipMessage[]): SkipMessage[] {
|
|
921
|
-
// Filter out delegation messages (administrative messages that shouldn't go to Skip)
|
|
922
|
-
const filteredMessages = messages.filter((msg) => !this.isDelegationMessage(msg.content));
|
|
923
|
-
|
|
924
|
-
// Enrich messages with default metadata if not already present
|
|
925
|
-
return filteredMessages.map((msg) => ({
|
|
926
|
-
...msg,
|
|
927
|
-
// Add default metadata fields if not already present
|
|
928
|
-
// Messages from DB already have conversationDetailID, temp messages get temp-X
|
|
929
|
-
hiddenToUser: msg.hiddenToUser ?? false,
|
|
930
|
-
userRating: msg.userRating ?? null,
|
|
931
|
-
userFeedback: msg.userFeedback ?? null,
|
|
932
|
-
reflectionInsights: msg.reflectionInsights ?? null,
|
|
933
|
-
summaryOfEarlierConveration: msg.summaryOfEarlierConveration ?? null,
|
|
934
|
-
}));
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
/**
|
|
938
|
-
* Check if a message is a delegation message that should be filtered out
|
|
939
|
-
* Uses flexible pattern matching to detect variations of delegation messages
|
|
940
|
-
*/
|
|
941
|
-
private isDelegationMessage(content: string): boolean {
|
|
942
|
-
if (!content) return false;
|
|
943
|
-
|
|
944
|
-
const lowerContent = content.toLowerCase();
|
|
945
|
-
|
|
946
|
-
// Check for both "delegating" or "delegate" AND "skip" in any order
|
|
947
|
-
const hasDelegatingOrDelegate = lowerContent.includes('delegating') || lowerContent.includes('delegate');
|
|
948
|
-
const hasSkip = lowerContent.includes('skip');
|
|
949
|
-
|
|
950
|
-
return hasDelegatingOrDelegate && hasSkip;
|
|
951
|
-
}
|
|
952
926
|
}
|