@memberjunction/server 2.102.0 → 2.104.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/skip-agent.d.ts +29 -0
- package/dist/agents/skip-agent.d.ts.map +1 -0
- package/dist/agents/skip-agent.js +143 -0
- package/dist/agents/skip-agent.js.map +1 -0
- package/dist/agents/skip-sdk.d.ts +47 -0
- package/dist/agents/skip-sdk.d.ts.map +1 -0
- package/dist/agents/skip-sdk.js +270 -0
- package/dist/agents/skip-sdk.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/generated/generated.d.ts +121 -16
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +829 -120
- package/dist/generated/generated.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +24 -9
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.d.ts +19 -0
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +140 -2
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +3 -3
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +16 -13
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/package.json +40 -40
- package/src/agents/skip-agent.ts +285 -0
- package/src/agents/skip-sdk.ts +543 -0
- package/src/config.ts +3 -2
- package/src/generated/generated.ts +544 -93
- package/src/resolvers/AskSkipResolver.ts +32 -10
- package/src/resolvers/ComponentRegistryResolver.ts +133 -4
- package/src/resolvers/RunAIAgentResolver.ts +16 -10
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skip Proxy Agent
|
|
3
|
+
*
|
|
4
|
+
* A proxy agent that integrates Skip SaaS API into the MemberJunction agent framework.
|
|
5
|
+
* This agent acts as a bridge, allowing Skip to be invoked like any other MJ agent
|
|
6
|
+
* while maintaining compatibility with the existing Skip infrastructure.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { BaseAgent } from "@memberjunction/ai-agents";
|
|
10
|
+
import {
|
|
11
|
+
ExecuteAgentParams,
|
|
12
|
+
AgentConfiguration,
|
|
13
|
+
BaseAgentNextStep
|
|
14
|
+
} from "@memberjunction/ai-core-plus";
|
|
15
|
+
import {
|
|
16
|
+
SkipAPIResponse,
|
|
17
|
+
SkipAPIAnalysisCompleteResponse,
|
|
18
|
+
SkipAPIClarifyingQuestionResponse,
|
|
19
|
+
SkipMessage
|
|
20
|
+
} from "@memberjunction/skip-types";
|
|
21
|
+
import { SkipSDK, SkipCallOptions } from "./skip-sdk.js";
|
|
22
|
+
import { DataContext } from "@memberjunction/data-context";
|
|
23
|
+
import { LogStatus, LogError } from "@memberjunction/core";
|
|
24
|
+
import { ChatMessage } from "@memberjunction/ai";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Context type for Skip agent execution
|
|
28
|
+
*/
|
|
29
|
+
export interface SkipAgentContext {
|
|
30
|
+
/**
|
|
31
|
+
* Optional data context ID to load
|
|
32
|
+
*/
|
|
33
|
+
dataContextId?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Optional pre-loaded data context
|
|
37
|
+
*/
|
|
38
|
+
dataContext?: DataContext;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Conversation ID for tracking Skip conversations
|
|
42
|
+
*/
|
|
43
|
+
conversationId?: string;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Force entity metadata refresh
|
|
47
|
+
*/
|
|
48
|
+
forceEntityRefresh?: boolean;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Database connection (injected by caller)
|
|
52
|
+
*/
|
|
53
|
+
dataSource?: any;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Payload returned from Skip agent execution
|
|
58
|
+
* Contains the full Skip API response for downstream consumers
|
|
59
|
+
*/
|
|
60
|
+
export interface SkipAgentPayload {
|
|
61
|
+
/**
|
|
62
|
+
* The full Skip API response
|
|
63
|
+
*/
|
|
64
|
+
skipResponse: SkipAPIResponse;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Response phase from Skip
|
|
68
|
+
*/
|
|
69
|
+
responsePhase: string;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Conversation ID
|
|
73
|
+
*/
|
|
74
|
+
conversationId: string;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* User-facing message (title or clarifying question)
|
|
78
|
+
*/
|
|
79
|
+
message?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Skip Proxy Agent
|
|
84
|
+
*
|
|
85
|
+
* This agent provides a simple proxy to the Skip SaaS API, allowing Skip to be
|
|
86
|
+
* invoked through the standard MJ agent framework. It handles:
|
|
87
|
+
* - Converting MJ conversation messages to Skip format
|
|
88
|
+
* - Streaming progress updates from Skip
|
|
89
|
+
* - Mapping Skip responses to MJ agent next steps
|
|
90
|
+
* - Returning full Skip responses in the payload
|
|
91
|
+
*/
|
|
92
|
+
export class SkipProxyAgent extends BaseAgent {
|
|
93
|
+
private skipSDK: SkipSDK;
|
|
94
|
+
|
|
95
|
+
constructor() {
|
|
96
|
+
super();
|
|
97
|
+
this.skipSDK = new SkipSDK();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Execute the Skip agent - proxies to Skip SaaS API
|
|
102
|
+
*/
|
|
103
|
+
protected override async executeAgentInternal<P = SkipAgentPayload>(
|
|
104
|
+
params: ExecuteAgentParams<SkipAgentContext, P>,
|
|
105
|
+
config: AgentConfiguration
|
|
106
|
+
): Promise<{ finalStep: BaseAgentNextStep<P>; stepCount: number; }> {
|
|
107
|
+
|
|
108
|
+
LogStatus(`[SkipProxyAgent] Starting Skip agent execution`);
|
|
109
|
+
|
|
110
|
+
// Extract context
|
|
111
|
+
const context = params.context || {} as SkipAgentContext;
|
|
112
|
+
const conversationId = context.conversationId || this.generateConversationId();
|
|
113
|
+
|
|
114
|
+
// Validate required parameters
|
|
115
|
+
if (!context.dataSource) {
|
|
116
|
+
LogError('[SkipProxyAgent] dataSource is required in context');
|
|
117
|
+
return {
|
|
118
|
+
finalStep: {
|
|
119
|
+
terminate: true,
|
|
120
|
+
step: 'Failed',
|
|
121
|
+
message: 'Missing required dataSource in context',
|
|
122
|
+
errorMessage: 'Missing required dataSource in context'
|
|
123
|
+
} as BaseAgentNextStep<P>,
|
|
124
|
+
stepCount: 1
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!params.contextUser) {
|
|
129
|
+
LogError('[SkipProxyAgent] contextUser is required');
|
|
130
|
+
return {
|
|
131
|
+
finalStep: {
|
|
132
|
+
terminate: true,
|
|
133
|
+
step: 'Failed',
|
|
134
|
+
message: 'Missing required contextUser',
|
|
135
|
+
errorMessage: 'Missing required contextUser'
|
|
136
|
+
} as BaseAgentNextStep<P>,
|
|
137
|
+
stepCount: 1
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Convert MJ conversation messages to Skip format
|
|
142
|
+
const skipMessages = this.convertMessagesToSkipFormat(params.conversationMessages || []);
|
|
143
|
+
|
|
144
|
+
// Prepare Skip SDK call options
|
|
145
|
+
const skipOptions: SkipCallOptions = {
|
|
146
|
+
messages: skipMessages,
|
|
147
|
+
conversationId,
|
|
148
|
+
dataContext: context.dataContext,
|
|
149
|
+
requestPhase: 'initial_request', // Could be parameterized if needed
|
|
150
|
+
contextUser: params.contextUser,
|
|
151
|
+
dataSource: context.dataSource,
|
|
152
|
+
includeEntities: true,
|
|
153
|
+
includeQueries: true,
|
|
154
|
+
includeNotes: true,
|
|
155
|
+
includeRequests: false,
|
|
156
|
+
forceEntityRefresh: context.forceEntityRefresh || false,
|
|
157
|
+
includeCallbackAuth: true,
|
|
158
|
+
onStatusUpdate: (message: string, responsePhase?: string) => {
|
|
159
|
+
// Forward Skip status updates to MJ progress callback
|
|
160
|
+
if (params.onProgress) {
|
|
161
|
+
params.onProgress({
|
|
162
|
+
step: 'prompt_execution', // Skip execution is essentially a prompt to an external service
|
|
163
|
+
message,
|
|
164
|
+
percentage: 0, // Skip doesn't provide percentage
|
|
165
|
+
metadata: {
|
|
166
|
+
conversationId,
|
|
167
|
+
responsePhase
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Call Skip API
|
|
175
|
+
const result = await this.skipSDK.chat(skipOptions);
|
|
176
|
+
|
|
177
|
+
// Handle Skip API errors
|
|
178
|
+
if (!result.success || !result.response) {
|
|
179
|
+
LogError(`[SkipProxyAgent] Skip API call failed: ${result.error}`);
|
|
180
|
+
return {
|
|
181
|
+
finalStep: {
|
|
182
|
+
terminate: true,
|
|
183
|
+
step: 'Failed',
|
|
184
|
+
message: 'Skip API call failed',
|
|
185
|
+
errorMessage: result.error
|
|
186
|
+
} as BaseAgentNextStep<P>,
|
|
187
|
+
stepCount: 1
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Map Skip response to MJ agent next step
|
|
192
|
+
const nextStep = this.mapSkipResponseToNextStep(result.response, conversationId);
|
|
193
|
+
|
|
194
|
+
LogStatus(`[SkipProxyAgent] Skip execution completed with phase: ${result.responsePhase}`);
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
finalStep: nextStep as BaseAgentNextStep<P>,
|
|
198
|
+
stepCount: 1 // Skip is a single-step proxy
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Convert MJ ChatMessage format to Skip SkipMessage format
|
|
204
|
+
*/
|
|
205
|
+
private convertMessagesToSkipFormat(messages: ChatMessage[]): SkipMessage[] {
|
|
206
|
+
return messages.map((msg, index) => ({
|
|
207
|
+
// Skip only accepts 'user' or 'system' roles, map 'assistant' to 'system'
|
|
208
|
+
role: (msg.role === 'assistant' ? 'system' : msg.role) as 'user' | 'system',
|
|
209
|
+
content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content),
|
|
210
|
+
conversationDetailID: `temp-${index}` // Temporary ID for messages without real IDs
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Map Skip API response to MJ agent next step
|
|
216
|
+
*/
|
|
217
|
+
private mapSkipResponseToNextStep(
|
|
218
|
+
apiResponse: SkipAPIResponse,
|
|
219
|
+
conversationId: string
|
|
220
|
+
): BaseAgentNextStep<SkipAgentPayload> {
|
|
221
|
+
|
|
222
|
+
// Build the payload with full Skip response
|
|
223
|
+
const payload: SkipAgentPayload = {
|
|
224
|
+
skipResponse: apiResponse,
|
|
225
|
+
responsePhase: apiResponse.responsePhase,
|
|
226
|
+
conversationId
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
switch (apiResponse.responsePhase) {
|
|
230
|
+
case 'analysis_complete': {
|
|
231
|
+
// Skip has completed analysis and returned results
|
|
232
|
+
const completeResponse = apiResponse as SkipAPIAnalysisCompleteResponse;
|
|
233
|
+
payload.message = completeResponse.title || 'Analysis complete';
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
terminate: true,
|
|
237
|
+
step: 'Success',
|
|
238
|
+
message: payload.message,
|
|
239
|
+
newPayload: payload
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
case 'clarifying_question': {
|
|
244
|
+
// Skip needs more information from the user
|
|
245
|
+
const clarifyResponse = apiResponse as SkipAPIClarifyingQuestionResponse;
|
|
246
|
+
payload.message = clarifyResponse.clarifyingQuestion;
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
terminate: true,
|
|
250
|
+
step: 'Chat',
|
|
251
|
+
message: clarifyResponse.clarifyingQuestion,
|
|
252
|
+
newPayload: payload
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
default: {
|
|
257
|
+
// Unknown or unexpected response phase
|
|
258
|
+
LogError(`[SkipProxyAgent] Unknown Skip response phase: ${apiResponse.responsePhase}`);
|
|
259
|
+
return {
|
|
260
|
+
terminate: true,
|
|
261
|
+
step: 'Failed',
|
|
262
|
+
message: `Unknown Skip response phase: ${apiResponse.responsePhase}`,
|
|
263
|
+
errorMessage: `Unknown Skip response phase: ${apiResponse.responsePhase}`,
|
|
264
|
+
newPayload: payload
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Generate a new conversation ID
|
|
272
|
+
*/
|
|
273
|
+
private generateConversationId(): string {
|
|
274
|
+
// Use crypto.randomUUID() if available, otherwise fallback
|
|
275
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
276
|
+
return crypto.randomUUID();
|
|
277
|
+
}
|
|
278
|
+
// Fallback UUID generation
|
|
279
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
280
|
+
const r = Math.random() * 16 | 0;
|
|
281
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
282
|
+
return v.toString(16);
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|