@memberjunction/server 2.103.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.
Files changed (35) hide show
  1. package/dist/agents/skip-agent.d.ts +29 -0
  2. package/dist/agents/skip-agent.d.ts.map +1 -0
  3. package/dist/agents/skip-agent.js +143 -0
  4. package/dist/agents/skip-agent.js.map +1 -0
  5. package/dist/agents/skip-sdk.d.ts +47 -0
  6. package/dist/agents/skip-sdk.d.ts.map +1 -0
  7. package/dist/agents/skip-sdk.js +270 -0
  8. package/dist/agents/skip-sdk.js.map +1 -0
  9. package/dist/config.d.ts +9 -0
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +1 -0
  12. package/dist/config.js.map +1 -1
  13. package/dist/generated/generated.d.ts +76 -16
  14. package/dist/generated/generated.d.ts.map +1 -1
  15. package/dist/generated/generated.js +527 -120
  16. package/dist/generated/generated.js.map +1 -1
  17. package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
  18. package/dist/resolvers/AskSkipResolver.js +24 -9
  19. package/dist/resolvers/AskSkipResolver.js.map +1 -1
  20. package/dist/resolvers/ComponentRegistryResolver.d.ts +19 -0
  21. package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
  22. package/dist/resolvers/ComponentRegistryResolver.js +140 -2
  23. package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
  24. package/dist/resolvers/RunAIAgentResolver.d.ts +3 -3
  25. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  26. package/dist/resolvers/RunAIAgentResolver.js +16 -13
  27. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  28. package/package.json +38 -38
  29. package/src/agents/skip-agent.ts +285 -0
  30. package/src/agents/skip-sdk.ts +543 -0
  31. package/src/config.ts +3 -2
  32. package/src/generated/generated.ts +351 -93
  33. package/src/resolvers/AskSkipResolver.ts +32 -10
  34. package/src/resolvers/ComponentRegistryResolver.ts +133 -4
  35. 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
+ }