@memberjunction/server 2.103.0 → 2.105.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 (93) 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 +1308 -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 +269 -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 +3660 -3386
  14. package/dist/generated/generated.d.ts.map +1 -1
  15. package/dist/generated/generated.js +22009 -20223
  16. package/dist/generated/generated.js.map +1 -1
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +5 -18
  20. package/dist/index.js.map +1 -1
  21. package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
  22. package/dist/resolvers/AskSkipResolver.js +24 -9
  23. package/dist/resolvers/AskSkipResolver.js.map +1 -1
  24. package/dist/resolvers/ComponentRegistryResolver.d.ts +19 -0
  25. package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
  26. package/dist/resolvers/ComponentRegistryResolver.js +140 -2
  27. package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
  28. package/dist/resolvers/CreateQueryResolver.d.ts +2 -2
  29. package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
  30. package/dist/resolvers/CreateQueryResolver.js +12 -12
  31. package/dist/resolvers/CreateQueryResolver.js.map +1 -1
  32. package/dist/resolvers/EntityResolver.d.ts +2 -2
  33. package/dist/resolvers/EntityResolver.d.ts.map +1 -1
  34. package/dist/resolvers/EntityResolver.js +4 -4
  35. package/dist/resolvers/EntityResolver.js.map +1 -1
  36. package/dist/resolvers/FileCategoryResolver.d.ts +1 -1
  37. package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
  38. package/dist/resolvers/FileCategoryResolver.js +2 -2
  39. package/dist/resolvers/FileCategoryResolver.js.map +1 -1
  40. package/dist/resolvers/FileResolver.d.ts +6 -6
  41. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  42. package/dist/resolvers/FileResolver.js +14 -14
  43. package/dist/resolvers/FileResolver.js.map +1 -1
  44. package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
  45. package/dist/resolvers/PotentialDuplicateRecordResolver.js +0 -2
  46. package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
  47. package/dist/resolvers/RunAIAgentResolver.d.ts +3 -3
  48. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  49. package/dist/resolvers/RunAIAgentResolver.js +28 -21
  50. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  51. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  52. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  53. package/dist/resolvers/TaskResolver.d.ts +18 -0
  54. package/dist/resolvers/TaskResolver.d.ts.map +1 -0
  55. package/dist/resolvers/TaskResolver.js +138 -0
  56. package/dist/resolvers/TaskResolver.js.map +1 -0
  57. package/dist/resolvers/UserFavoriteResolver.d.ts +2 -2
  58. package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
  59. package/dist/resolvers/UserFavoriteResolver.js +5 -5
  60. package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
  61. package/dist/resolvers/UserResolver.d.ts +2 -2
  62. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  63. package/dist/resolvers/UserResolver.js +7 -7
  64. package/dist/resolvers/UserResolver.js.map +1 -1
  65. package/dist/resolvers/UserViewResolver.d.ts +2 -2
  66. package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
  67. package/dist/resolvers/UserViewResolver.js +8 -8
  68. package/dist/resolvers/UserViewResolver.js.map +1 -1
  69. package/dist/services/TaskOrchestrator.d.ts +52 -0
  70. package/dist/services/TaskOrchestrator.d.ts.map +1 -0
  71. package/dist/services/TaskOrchestrator.js +486 -0
  72. package/dist/services/TaskOrchestrator.js.map +1 -0
  73. package/package.json +30 -38
  74. package/src/agents/skip-agent.ts +1433 -0
  75. package/src/agents/skip-sdk.ts +541 -0
  76. package/src/config.ts +3 -2
  77. package/src/generated/generated.ts +7948 -6811
  78. package/src/index.ts +7 -21
  79. package/src/resolvers/AskSkipResolver.ts +32 -10
  80. package/src/resolvers/ComponentRegistryResolver.ts +133 -4
  81. package/src/resolvers/CreateQueryResolver.ts +6 -6
  82. package/src/resolvers/EntityResolver.ts +4 -4
  83. package/src/resolvers/FileCategoryResolver.ts +2 -2
  84. package/src/resolvers/FileResolver.ts +12 -12
  85. package/src/resolvers/PotentialDuplicateRecordResolver.ts +2 -3
  86. package/src/resolvers/RunAIAgentResolver.ts +23 -10
  87. package/src/resolvers/RunTemplateResolver.ts +1 -2
  88. package/src/resolvers/TaskResolver.ts +142 -0
  89. package/src/resolvers/UserFavoriteResolver.ts +5 -5
  90. package/src/resolvers/UserResolver.ts +7 -7
  91. package/src/resolvers/UserViewResolver.ts +8 -8
  92. package/src/services/TaskOrchestration-Integration.md +188 -0
  93. package/src/services/TaskOrchestrator.ts +756 -0
@@ -0,0 +1,541 @@
1
+ /**
2
+ * Skip TypeScript SDK
3
+ *
4
+ * A general-purpose SDK for calling the Skip SaaS API.
5
+ * This module provides a clean, reusable interface for integrating with Skip
6
+ * that can eventually be extracted into a standalone npm package.
7
+ */
8
+
9
+ import {
10
+ SkipAPIRequest,
11
+ SkipAPIResponse,
12
+ SkipMessage,
13
+ SkipAPIAnalysisCompleteResponse,
14
+ SkipAPIClarifyingQuestionResponse,
15
+ SkipRequestPhase,
16
+ SkipAPIRequestAPIKey,
17
+ SkipQueryInfo,
18
+ SkipEntityInfo,
19
+ SkipAPIAgentNote,
20
+ SkipAPIAgentNoteType,
21
+ SkipAPIArtifact
22
+ } from '@memberjunction/skip-types';
23
+ import { DataContext } from '@memberjunction/data-context';
24
+ import { UserInfo, LogStatus, LogError, Metadata, RunView } from '@memberjunction/core';
25
+ import { sendPostRequest } from '../util.js';
26
+ import { configInfo, baseUrl, publicUrl, graphqlPort, graphqlRootPath, apiKey as callbackAPIKey } from '../config.js';
27
+ import { GetAIAPIKey } from '@memberjunction/ai';
28
+ import { CopyScalarsAndArrays } from '@memberjunction/global';
29
+ import mssql from 'mssql';
30
+ import { registerAccessToken, GetDataAccessToken } from '../resolvers/GetDataResolver.js';
31
+ import { ConversationArtifactEntity, ConversationArtifactVersionEntity, ArtifactTypeEntity } from '@memberjunction/core-entities';
32
+
33
+ /**
34
+ * Configuration options for Skip SDK
35
+ */
36
+ export interface SkipSDKConfig {
37
+ /**
38
+ * Skip API base URL (e.g., 'https://skip.memberjunction.com')
39
+ */
40
+ apiUrl?: string;
41
+
42
+ /**
43
+ * Skip API key for authentication
44
+ */
45
+ apiKey?: string;
46
+
47
+ /**
48
+ * Organization ID
49
+ */
50
+ organizationId?: string;
51
+
52
+ /**
53
+ * Optional organization context information
54
+ */
55
+ organizationInfo?: string;
56
+ }
57
+
58
+ /**
59
+ * Options for making a Skip API call
60
+ */
61
+ export interface SkipCallOptions {
62
+ /**
63
+ * Conversation messages (user/assistant)
64
+ */
65
+ messages: SkipMessage[];
66
+
67
+ /**
68
+ * Conversation ID for tracking
69
+ */
70
+ conversationId: string;
71
+
72
+ /**
73
+ * Data context to provide to Skip
74
+ */
75
+ dataContext?: DataContext;
76
+
77
+ /**
78
+ * Request phase (initial_request, clarify_question_response, etc.)
79
+ */
80
+ requestPhase?: SkipRequestPhase;
81
+
82
+ /**
83
+ * Context user for permissions and metadata
84
+ */
85
+ contextUser: UserInfo;
86
+
87
+ /**
88
+ * Database connection for metadata queries
89
+ */
90
+ dataSource: mssql.ConnectionPool;
91
+
92
+ /**
93
+ * Include entity metadata in request
94
+ */
95
+ includeEntities?: boolean;
96
+
97
+ /**
98
+ * Include saved queries in request
99
+ */
100
+ includeQueries?: boolean;
101
+
102
+ /**
103
+ * Include agent notes in request
104
+ */
105
+ includeNotes?: boolean;
106
+
107
+ /**
108
+ * Include agent requests in request
109
+ */
110
+ includeRequests?: boolean;
111
+
112
+ /**
113
+ * Force refresh of entity metadata cache
114
+ */
115
+ forceEntityRefresh?: boolean;
116
+
117
+ /**
118
+ * Include callback API key and access token for Skip to call back to MJ
119
+ */
120
+ includeCallbackAuth?: boolean;
121
+
122
+ /**
123
+ * Callback for streaming status updates during execution
124
+ */
125
+ onStatusUpdate?: (message: string, responsePhase?: string) => void;
126
+ }
127
+
128
+ /**
129
+ * Result from a Skip API call
130
+ */
131
+ export interface SkipCallResult {
132
+ /**
133
+ * Whether the call was successful
134
+ */
135
+ success: boolean;
136
+
137
+ /**
138
+ * The final Skip API response
139
+ */
140
+ response?: SkipAPIResponse;
141
+
142
+ /**
143
+ * Response phase (analysis_complete, clarifying_question, status_update)
144
+ */
145
+ responsePhase?: string;
146
+
147
+ /**
148
+ * Error message if failed
149
+ */
150
+ error?: string;
151
+
152
+ /**
153
+ * All streaming responses received (including intermediate status updates)
154
+ */
155
+ allResponses?: any[];
156
+ }
157
+
158
+ /**
159
+ * Skip TypeScript SDK
160
+ * Provides a clean interface for calling the Skip SaaS API
161
+ */
162
+ export class SkipSDK {
163
+ private config: SkipSDKConfig;
164
+
165
+ constructor(config?: SkipSDKConfig) {
166
+ // Use provided config or fall back to MJ server config
167
+ this.config = {
168
+ apiUrl: config?.apiUrl || configInfo.askSkip?.chatURL,
169
+ apiKey: config?.apiKey || configInfo.askSkip?.apiKey,
170
+ organizationId: config?.organizationId || configInfo.askSkip?.orgID,
171
+ organizationInfo: config?.organizationInfo || configInfo.askSkip?.organizationInfo
172
+ };
173
+ }
174
+
175
+ /**
176
+ * Call the Skip chat API
177
+ */
178
+ async chat(options: SkipCallOptions): Promise<SkipCallResult> {
179
+ LogStatus(`[SkipSDK] Sending request to Skip API: ${this.config.apiUrl}`);
180
+
181
+ try {
182
+ // Build the Skip API request
183
+ const skipRequest = await this.buildSkipRequest(options);
184
+
185
+ // Call Skip API with streaming support
186
+ const responses = await sendPostRequest(
187
+ this.config.apiUrl,
188
+ skipRequest,
189
+ true, // useCompression
190
+ this.buildHeaders(),
191
+ (streamMessage: any) => {
192
+ // Handle streaming status updates
193
+ if (streamMessage.type === 'status_update' && options.onStatusUpdate) {
194
+ const statusContent = streamMessage.value?.messages?.[0]?.content;
195
+ const responsePhase = streamMessage.value?.responsePhase;
196
+ if (statusContent) {
197
+ options.onStatusUpdate(statusContent, responsePhase);
198
+ }
199
+ }
200
+ }
201
+ );
202
+
203
+ // The last response is the final one
204
+ if (responses && responses.length > 0) {
205
+ const finalResponse = responses[responses.length - 1].value as SkipAPIResponse;
206
+
207
+ return {
208
+ success: true,
209
+ response: finalResponse,
210
+ responsePhase: finalResponse.responsePhase,
211
+ allResponses: responses
212
+ };
213
+ } else {
214
+ return {
215
+ success: false,
216
+ error: 'No response received from Skip API'
217
+ };
218
+ }
219
+
220
+ } catch (error) {
221
+ LogError(`[SkipSDK] Error calling Skip API: ${error}`);
222
+ return {
223
+ success: false,
224
+ error: String(error)
225
+ };
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Build the Skip API request object
231
+ */
232
+ private async buildSkipRequest(options: SkipCallOptions): Promise<SkipAPIRequest> {
233
+ const {
234
+ messages,
235
+ conversationId,
236
+ dataContext,
237
+ requestPhase = 'initial_request',
238
+ contextUser,
239
+ dataSource,
240
+ includeEntities = true,
241
+ includeQueries = true,
242
+ includeNotes = true,
243
+ includeRequests = false,
244
+ forceEntityRefresh = false,
245
+ includeCallbackAuth = true
246
+ } = options;
247
+
248
+ // Build base request with metadata
249
+ const baseRequest = await this.buildBaseRequest(
250
+ contextUser,
251
+ dataSource,
252
+ includeEntities,
253
+ includeQueries,
254
+ includeNotes,
255
+ includeRequests,
256
+ forceEntityRefresh,
257
+ includeCallbackAuth,
258
+ { conversationId, requestPhase }
259
+ );
260
+
261
+ // Build artifacts for this conversation
262
+ const artifacts = await this.buildArtifacts(contextUser, dataSource, conversationId);
263
+
264
+ // Construct the full Skip API request
265
+ const request: SkipAPIRequest = {
266
+ messages,
267
+ conversationID: conversationId,
268
+ dataContext: dataContext ? CopyScalarsAndArrays(dataContext) as DataContext : undefined,
269
+ requestPhase,
270
+ artifacts,
271
+ entities: baseRequest.entities || [],
272
+ queries: baseRequest.queries || [],
273
+ notes: baseRequest.notes,
274
+ noteTypes: baseRequest.noteTypes,
275
+ userEmail: baseRequest.userEmail,
276
+ organizationID: baseRequest.organizationID,
277
+ organizationInfo: baseRequest.organizationInfo,
278
+ apiKeys: baseRequest.apiKeys,
279
+ callingServerURL: baseRequest.callingServerURL,
280
+ callingServerAPIKey: baseRequest.callingServerAPIKey,
281
+ callingServerAccessToken: baseRequest.callingServerAccessToken
282
+ };
283
+
284
+ return request;
285
+ }
286
+
287
+ /**
288
+ * Build base request with metadata, API keys, and callback auth
289
+ */
290
+ private async buildBaseRequest(
291
+ contextUser: UserInfo,
292
+ dataSource: mssql.ConnectionPool,
293
+ includeEntities: boolean,
294
+ includeQueries: boolean,
295
+ includeNotes: boolean,
296
+ includeRequests: boolean,
297
+ forceEntityRefresh: boolean,
298
+ includeCallbackAuth: boolean,
299
+ additionalTokenInfo: any = {}
300
+ ): Promise<Partial<SkipAPIRequest>> {
301
+ const entities = includeEntities ? await this.buildEntities(dataSource, forceEntityRefresh) : [];
302
+ const queries = includeQueries ? this.buildQueries() : [];
303
+ const { notes, noteTypes } = includeNotes ? await this.buildAgentNotes(contextUser) : { notes: [], noteTypes: [] };
304
+ // Note: requests would be built here if includeRequests is true
305
+
306
+ // Setup access token for Skip callbacks if needed
307
+ let accessToken: GetDataAccessToken | undefined;
308
+ if (includeCallbackAuth) {
309
+ const tokenInfo = {
310
+ type: 'skip_api_request',
311
+ userEmail: contextUser.Email,
312
+ userName: contextUser.Name,
313
+ userID: contextUser.ID,
314
+ ...additionalTokenInfo
315
+ };
316
+
317
+ accessToken = registerAccessToken(
318
+ undefined,
319
+ 1000 * 60 * 10, // 10 minutes
320
+ tokenInfo
321
+ );
322
+ }
323
+
324
+ return {
325
+ entities,
326
+ queries,
327
+ notes,
328
+ noteTypes,
329
+ userEmail: contextUser.Email,
330
+ organizationID: this.config.organizationId,
331
+ organizationInfo: this.config.organizationInfo,
332
+ apiKeys: this.buildAPIKeys(),
333
+ callingServerURL: accessToken ? (publicUrl || `${baseUrl}:${graphqlPort}${graphqlRootPath}`) : undefined,
334
+ callingServerAPIKey: accessToken ? callbackAPIKey : undefined,
335
+ callingServerAccessToken: accessToken ? accessToken.Token : undefined
336
+ };
337
+ }
338
+
339
+ /**
340
+ * Build entity metadata for Skip
341
+ * This can be extracted from AskSkipResolver.BuildSkipEntities if needed
342
+ */
343
+ private async buildEntities(dataSource: mssql.ConnectionPool, forceRefresh: boolean): Promise<SkipEntityInfo[]> {
344
+ // TODO: Implement entity metadata building
345
+ // This would typically query the metadata and convert to SkipEntityInfo format
346
+ // For now, returning empty array - can be populated later
347
+ return [];
348
+ }
349
+
350
+ /**
351
+ * Build saved queries for Skip
352
+ */
353
+ private buildQueries(status: "Pending" | "In-Review" | "Approved" | "Rejected" | "Obsolete" = 'Approved'): SkipQueryInfo[] {
354
+ const md = new Metadata();
355
+ const approvedQueries = md.Queries.filter((q) => q.Status === status);
356
+
357
+ return approvedQueries.map((q) => ({
358
+ id: q.ID,
359
+ name: q.Name,
360
+ description: q.Description,
361
+ category: q.Category,
362
+ categoryPath: this.buildQueryCategoryPath(md, q.CategoryID),
363
+ sql: q.SQL,
364
+ originalSQL: q.OriginalSQL,
365
+ feedback: q.Feedback,
366
+ status: q.Status,
367
+ qualityRank: q.QualityRank,
368
+ createdAt: q.__mj_CreatedAt,
369
+ updatedAt: q.__mj_UpdatedAt,
370
+ categoryID: q.CategoryID,
371
+ embeddingVector: q.EmbeddingVector,
372
+ embeddingModelID: q.EmbeddingModelID,
373
+ embeddingModelName: q.EmbeddingModel,
374
+ fields: q.Fields.map((f) => ({
375
+ id: f.ID,
376
+ queryID: f.QueryID,
377
+ sequence: f.Sequence,
378
+ name: f.Name,
379
+ description: f.Description,
380
+ sqlBaseType: f.SQLBaseType,
381
+ sqlFullType: f.SQLFullType,
382
+ sourceEntityID: f.SourceEntityID,
383
+ sourceEntity: f.SourceEntity,
384
+ sourceFieldName: f.SourceFieldName,
385
+ isComputed: f.IsComputed,
386
+ computationDescription: f.ComputationDescription,
387
+ isSummary: f.IsSummary,
388
+ summaryDescription: f.SummaryDescription,
389
+ createdAt: f.__mj_CreatedAt,
390
+ updatedAt: f.__mj_UpdatedAt
391
+ })),
392
+ params: q.Parameters.map((p) => ({
393
+ id: p.ID,
394
+ queryID: p.QueryID,
395
+ name: p.Name,
396
+ description: p.Description,
397
+ type: p.Type,
398
+ isRequired: p.IsRequired,
399
+ // LinkedParameterName and LinkedParameterType may not exist on QueryParameterInfo
400
+ defaultValue: p.DefaultValue,
401
+ createdAt: p.__mj_CreatedAt,
402
+ updatedAt: p.__mj_UpdatedAt
403
+ }))
404
+ }));
405
+ }
406
+
407
+ /**
408
+ * Recursively build category path for a query
409
+ */
410
+ private buildQueryCategoryPath(md: Metadata, categoryID: string): string {
411
+ const cat = md.QueryCategories.find((c) => c.ID === categoryID);
412
+ if (!cat) return '';
413
+ if (!cat.ParentID) return cat.Name;
414
+ const parentPath = this.buildQueryCategoryPath(md, cat.ParentID);
415
+ return parentPath ? `${parentPath}/${cat.Name}` : cat.Name;
416
+ }
417
+
418
+ /**
419
+ * Build agent notes for Skip
420
+ */
421
+ private async buildAgentNotes(contextUser: UserInfo): Promise<{ notes: SkipAPIAgentNote[], noteTypes: SkipAPIAgentNoteType[] }> {
422
+ // TODO: Implement agent notes building
423
+ // This would query AIAgentNote entities and convert to SkipAPIAgentNote format
424
+ // For now, returning empty arrays
425
+ return { notes: [], noteTypes: [] };
426
+ }
427
+
428
+ /**
429
+ * Build artifacts for a conversation
430
+ */
431
+ private async buildArtifacts(contextUser: UserInfo, dataSource: mssql.ConnectionPool, conversationId: string): Promise<SkipAPIArtifact[]> {
432
+ const md = new Metadata();
433
+ const ei = md.EntityByName('MJ: Conversation Artifacts');
434
+ const rv = new RunView();
435
+
436
+ const results = await rv.RunViews([
437
+ {
438
+ EntityName: "MJ: Conversation Artifacts",
439
+ ExtraFilter: `ConversationID='${conversationId}'`,
440
+ OrderBy: "__mj_CreatedAt"
441
+ },
442
+ {
443
+ EntityName: "MJ: Artifact Types",
444
+ OrderBy: "Name"
445
+ },
446
+ {
447
+ EntityName: "MJ: Conversation Artifact Versions",
448
+ ExtraFilter: `ConversationArtifactID IN (SELECT ID FROM [${ei.SchemaName}].[${ei.BaseView}] WHERE ConversationID='${conversationId}')`,
449
+ OrderBy: 'ConversationArtifactID, __mj_CreatedAt'
450
+ }
451
+ ], contextUser);
452
+
453
+ if (!results || results.length === 0 || !results.every(r => r.Success)) {
454
+ return [];
455
+ }
456
+
457
+ const types = results[1].Results.map((a: ArtifactTypeEntity) => ({
458
+ id: a.ID,
459
+ name: a.Name,
460
+ description: a.Description,
461
+ contentType: a.ContentType,
462
+ enabled: a.IsEnabled,
463
+ createdAt: a.__mj_CreatedAt,
464
+ updatedAt: a.__mj_UpdatedAt
465
+ }));
466
+
467
+ const artifacts = results[0].Results.map((a: ConversationArtifactEntity) => {
468
+ const rawVersions: ConversationArtifactVersionEntity[] = results[2].Results as ConversationArtifactVersionEntity[];
469
+ const thisArtifactsVersions = rawVersions.filter(rv => rv.ConversationArtifactID === a.ID);
470
+
471
+ const versions = thisArtifactsVersions.map((v: ConversationArtifactVersionEntity) => ({
472
+ id: v.ID,
473
+ artifactId: v.ConversationArtifactID,
474
+ version: v.Version,
475
+ configuration: v.Configuration,
476
+ content: v.Content,
477
+ comments: v.Comments,
478
+ createdAt: v.__mj_CreatedAt,
479
+ updatedAt: v.__mj_UpdatedAt
480
+ }));
481
+
482
+ return {
483
+ id: a.ID,
484
+ conversationId: a.ConversationID,
485
+ name: a.Name,
486
+ description: a.Description,
487
+ artifactType: types.find(t => t.id === a.ArtifactTypeID),
488
+ sharingScope: a.SharingScope,
489
+ currentVersion: versions.length > 0 ? Math.max(...versions.map(v => v.version)) : 1,
490
+ versions,
491
+ comments: '', // Default empty comments since it's required
492
+ createdAt: a.__mj_CreatedAt,
493
+ updatedAt: a.__mj_UpdatedAt
494
+ };
495
+ });
496
+
497
+ return artifacts;
498
+ }
499
+
500
+ /**
501
+ * Build API keys for AI services
502
+ */
503
+ private buildAPIKeys(): SkipAPIRequestAPIKey[] {
504
+ return [
505
+ {
506
+ vendorDriverName: 'OpenAILLM',
507
+ apiKey: GetAIAPIKey('OpenAILLM')
508
+ },
509
+ {
510
+ vendorDriverName: 'AnthropicLLM',
511
+ apiKey: GetAIAPIKey('AnthropicLLM')
512
+ },
513
+ {
514
+ vendorDriverName: 'GeminiLLM',
515
+ apiKey: GetAIAPIKey('GeminiLLM')
516
+ },
517
+ {
518
+ vendorDriverName: 'GroqLLM',
519
+ apiKey: GetAIAPIKey('GroqLLM')
520
+ },
521
+ {
522
+ vendorDriverName: 'MistralLLM',
523
+ apiKey: GetAIAPIKey('MistralLLM')
524
+ },
525
+ {
526
+ vendorDriverName: 'CerebrasLLM',
527
+ apiKey: GetAIAPIKey('CerebrasLLM')
528
+ }
529
+ ];
530
+ }
531
+
532
+ /**
533
+ * Build HTTP headers for Skip API requests
534
+ */
535
+ private buildHeaders(): Record<string, string> {
536
+ return {
537
+ 'x-api-key': this.config.apiKey || '',
538
+ 'Content-Type': 'application/json'
539
+ };
540
+ }
541
+ }
package/src/config.ts CHANGED
@@ -68,6 +68,7 @@ const zodBooleanWithTransforms = () => {
68
68
  }
69
69
 
70
70
  const askSkipInfoSchema = z.object({
71
+ url: z.string().optional(), // Base URL for Skip API
71
72
  apiKey: z.string().optional(),
72
73
  orgID: z.string().optional(),
73
74
  organizationInfo: z.string().optional(),
@@ -78,8 +79,8 @@ const askSkipInfoSchema = z.object({
78
79
  })
79
80
  .optional(),
80
81
  chatURL: z.string().optional(),
81
- learningCycleRunUponStartup: zodBooleanWithTransforms(),
82
- learningCycleEnabled: zodBooleanWithTransforms(),
82
+ learningCycleRunUponStartup: zodBooleanWithTransforms(),
83
+ learningCycleEnabled: zodBooleanWithTransforms(),
83
84
  learningCycleURL: z.string().optional(),
84
85
  learningCycleIntervalInMinutes: z.coerce.number().optional(),
85
86
  });