@memberjunction/server 2.117.0 → 2.119.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-sdk.d.ts.map +1 -1
- package/dist/agents/skip-sdk.js +10 -0
- package/dist/agents/skip-sdk.js.map +1 -1
- package/dist/generated/generated.d.ts +653 -6
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +4033 -52
- package/dist/generated/generated.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +3 -4
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +32 -176
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunTestResolver.d.ts +41 -0
- package/dist/resolvers/RunTestResolver.d.ts.map +1 -0
- package/dist/resolvers/RunTestResolver.js +349 -0
- package/dist/resolvers/RunTestResolver.js.map +1 -0
- package/package.json +41 -40
- package/src/agents/skip-sdk.ts +10 -0
- package/src/generated/generated.ts +2557 -41
- package/src/resolvers/RunAIAgentResolver.ts +42 -292
- package/src/resolvers/RunTestResolver.ts +369 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Resolver, Mutation, Query, Arg, Ctx, ObjectType, Field, PubSub, PubSubEngine, Subscription, Root, ResolverFilterData, ID } from 'type-graphql';
|
|
2
2
|
import { AppContext, UserPayload } from '../types.js';
|
|
3
|
-
import { DatabaseProviderBase, LogError, LogStatus, Metadata,
|
|
4
|
-
import { AIAgentEntityExtended,
|
|
3
|
+
import { DatabaseProviderBase, LogError, LogStatus, Metadata, UserInfo } from '@memberjunction/core';
|
|
4
|
+
import { AIAgentEntityExtended, ConversationDetailEntity, UserNotificationEntity, AIAgentRunEntityExtended } from '@memberjunction/core-entities';
|
|
5
5
|
import { AgentRunner } from '@memberjunction/ai-agents';
|
|
6
6
|
import { ExecuteAgentResult } from '@memberjunction/ai-core-plus';
|
|
7
7
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
@@ -31,8 +31,8 @@ export class AgentExecutionProgress {
|
|
|
31
31
|
@Field()
|
|
32
32
|
currentStep: string;
|
|
33
33
|
|
|
34
|
-
@Field()
|
|
35
|
-
percentage
|
|
34
|
+
@Field({ nullable: true })
|
|
35
|
+
percentage?: number;
|
|
36
36
|
|
|
37
37
|
@Field()
|
|
38
38
|
message: string;
|
|
@@ -42,6 +42,12 @@ export class AgentExecutionProgress {
|
|
|
42
42
|
|
|
43
43
|
@Field({ nullable: true })
|
|
44
44
|
agentType?: string;
|
|
45
|
+
|
|
46
|
+
@Field({ nullable: true })
|
|
47
|
+
stepCount?: number;
|
|
48
|
+
|
|
49
|
+
@Field({ nullable: true })
|
|
50
|
+
hierarchicalStep?: string;
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
@ObjectType()
|
|
@@ -136,7 +142,9 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
136
142
|
const sanitized: any = {
|
|
137
143
|
success: result.success,
|
|
138
144
|
payload: result.payload,
|
|
139
|
-
|
|
145
|
+
responseForm: result.responseForm,
|
|
146
|
+
actionableCommands: result.actionableCommands,
|
|
147
|
+
automaticCommands: result.automaticCommands,
|
|
140
148
|
errorMessage: result.agentRun?.ErrorMessage,
|
|
141
149
|
finalStep: result.agentRun?.FinalStep,
|
|
142
150
|
cancelled: result.agentRun?.Status === 'Cancelled',
|
|
@@ -230,7 +238,9 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
230
238
|
percentage: progress.percentage,
|
|
231
239
|
message: progress.message,
|
|
232
240
|
agentName: (progress.metadata as any)?.agentName || undefined,
|
|
233
|
-
agentType: (progress.metadata as any)?.agentType || undefined
|
|
241
|
+
agentType: (progress.metadata as any)?.agentType || undefined,
|
|
242
|
+
stepCount: (progress.metadata as any)?.stepCount || undefined,
|
|
243
|
+
hierarchicalStep: (progress.metadata as any)?.hierarchicalStep || undefined
|
|
234
244
|
},
|
|
235
245
|
timestamp: new Date()
|
|
236
246
|
};
|
|
@@ -354,14 +364,14 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
354
364
|
// for multi-user server environments like this one
|
|
355
365
|
// Create AI agent runner
|
|
356
366
|
const agentRunner = new AgentRunner();
|
|
357
|
-
|
|
367
|
+
|
|
358
368
|
// Track agent run for streaming (use ref to update later)
|
|
359
369
|
const agentRunRef = { current: null as any };
|
|
360
370
|
|
|
361
371
|
console.log(`🚀 Starting agent execution with sessionId: ${sessionId}`);
|
|
362
372
|
|
|
363
|
-
// Execute the agent
|
|
364
|
-
const
|
|
373
|
+
// Execute the agent in conversation context - handles conversation, artifacts, etc.
|
|
374
|
+
const conversationResult = await agentRunner.RunAgentInConversation({
|
|
365
375
|
agent: agentEntity,
|
|
366
376
|
conversationMessages: parsedMessages,
|
|
367
377
|
payload: payload ? SafeJSONParse(payload) : undefined,
|
|
@@ -372,12 +382,20 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
372
382
|
autoPopulateLastRunPayload: autoPopulateLastRunPayload,
|
|
373
383
|
configurationId: configurationId,
|
|
374
384
|
data: parsedData,
|
|
375
|
-
conversationDetailId: conversationDetailId,
|
|
376
385
|
context: {
|
|
377
386
|
dataSource: dataSource
|
|
378
387
|
}
|
|
388
|
+
}, {
|
|
389
|
+
conversationDetailId: conversationDetailId, // Use existing if provided
|
|
390
|
+
createArtifacts: createArtifacts || false,
|
|
391
|
+
sourceArtifactId: sourceArtifactId
|
|
379
392
|
});
|
|
380
393
|
|
|
394
|
+
const result = conversationResult.agentResult;
|
|
395
|
+
// Use agent response detail ID if available, otherwise fall back to user message detail ID
|
|
396
|
+
const finalConversationDetailId = conversationResult.agentResponseDetailId || conversationResult.userMessageDetailId;
|
|
397
|
+
const artifactInfo = conversationResult.artifactInfo;
|
|
398
|
+
|
|
381
399
|
// Update agent run ref once available
|
|
382
400
|
if (result.agentRun) {
|
|
383
401
|
agentRunRef.current = result.agentRun;
|
|
@@ -388,35 +406,20 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
388
406
|
// Publish final events
|
|
389
407
|
this.publishFinalEvents(pubSub, sessionId, userPayload, result);
|
|
390
408
|
|
|
391
|
-
//
|
|
392
|
-
if (result.success &&
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if (createNotification && artifactInfo.artifactId && artifactInfo.versionId && artifactInfo.versionNumber) {
|
|
406
|
-
await this.createCompletionNotification(
|
|
407
|
-
result.agentRun,
|
|
408
|
-
{
|
|
409
|
-
artifactId: artifactInfo.artifactId,
|
|
410
|
-
versionId: artifactInfo.versionId,
|
|
411
|
-
versionNumber: artifactInfo.versionNumber
|
|
412
|
-
},
|
|
413
|
-
conversationDetailId,
|
|
414
|
-
currentUser,
|
|
415
|
-
pubSub,
|
|
416
|
-
userPayload
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
409
|
+
// Create notification if enabled and artifact was created successfully
|
|
410
|
+
if (createNotification && result.success && artifactInfo && artifactInfo.artifactId && artifactInfo.versionId && artifactInfo.versionNumber) {
|
|
411
|
+
await this.createCompletionNotification(
|
|
412
|
+
result.agentRun,
|
|
413
|
+
{
|
|
414
|
+
artifactId: artifactInfo.artifactId,
|
|
415
|
+
versionId: artifactInfo.versionId,
|
|
416
|
+
versionNumber: artifactInfo.versionNumber
|
|
417
|
+
},
|
|
418
|
+
finalConversationDetailId,
|
|
419
|
+
currentUser,
|
|
420
|
+
pubSub,
|
|
421
|
+
userPayload
|
|
422
|
+
);
|
|
420
423
|
}
|
|
421
424
|
|
|
422
425
|
// Create sanitized payload for JSON serialization
|
|
@@ -588,259 +591,6 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
588
591
|
);
|
|
589
592
|
}
|
|
590
593
|
|
|
591
|
-
/**
|
|
592
|
-
* Get the maximum version number for an artifact
|
|
593
|
-
* Used when creating new version of an explicitly specified artifact
|
|
594
|
-
*/
|
|
595
|
-
private async getMaxVersionForArtifact(
|
|
596
|
-
artifactId: string,
|
|
597
|
-
contextUser: UserInfo
|
|
598
|
-
): Promise<number> {
|
|
599
|
-
try {
|
|
600
|
-
const rv = new RunView();
|
|
601
|
-
|
|
602
|
-
// Query all versions for this artifact to find max version number
|
|
603
|
-
const result = await rv.RunView<ArtifactVersionEntity>({
|
|
604
|
-
EntityName: 'MJ: Artifact Versions',
|
|
605
|
-
ExtraFilter: `ArtifactID='${artifactId}'`,
|
|
606
|
-
OrderBy: 'VersionNumber DESC',
|
|
607
|
-
MaxRows: 1,
|
|
608
|
-
ResultType: 'entity_object'
|
|
609
|
-
}, contextUser);
|
|
610
|
-
|
|
611
|
-
if (result.Success && result.Results && result.Results.length > 0) {
|
|
612
|
-
return result.Results[0].VersionNumber || 0;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
return 0; // No versions found, will create version 1
|
|
616
|
-
} catch (error) {
|
|
617
|
-
LogError(`Error getting max version for artifact: ${(error as Error).message}`);
|
|
618
|
-
return 0;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
/**
|
|
623
|
-
* Find the most recent artifact for a conversation detail to determine versioning
|
|
624
|
-
* Returns artifact info if exists, null if this is first artifact
|
|
625
|
-
*/
|
|
626
|
-
private async findPreviousArtifactForMessage(
|
|
627
|
-
conversationDetailId: string,
|
|
628
|
-
contextUser: UserInfo
|
|
629
|
-
): Promise<{ artifactId: string; versionNumber: number } | null> {
|
|
630
|
-
try {
|
|
631
|
-
const rv = new RunView();
|
|
632
|
-
|
|
633
|
-
// Query junction table to find artifacts for this message
|
|
634
|
-
const result = await rv.RunView<ConversationDetailArtifactEntity>({
|
|
635
|
-
EntityName: 'MJ: Conversation Detail Artifacts',
|
|
636
|
-
ExtraFilter: `ConversationDetailID='${conversationDetailId}' AND Direction='Output'`,
|
|
637
|
-
OrderBy: '__mj_CreatedAt DESC',
|
|
638
|
-
MaxRows: 1,
|
|
639
|
-
ResultType: 'entity_object'
|
|
640
|
-
}, contextUser);
|
|
641
|
-
|
|
642
|
-
if (!result.Success || !result.Results || result.Results.length === 0) {
|
|
643
|
-
return null;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
const junction = result.Results[0];
|
|
647
|
-
|
|
648
|
-
// Load the artifact version to get version number and artifact ID
|
|
649
|
-
const md = new Metadata();
|
|
650
|
-
const version = await md.GetEntityObject<ArtifactVersionEntity>(
|
|
651
|
-
'MJ: Artifact Versions',
|
|
652
|
-
contextUser
|
|
653
|
-
);
|
|
654
|
-
|
|
655
|
-
if (!(await version.Load(junction.ArtifactVersionID))) {
|
|
656
|
-
return null;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
return {
|
|
660
|
-
artifactId: version.ArtifactID,
|
|
661
|
-
versionNumber: version.VersionNumber
|
|
662
|
-
};
|
|
663
|
-
} catch (error) {
|
|
664
|
-
LogError(`Error finding previous artifact: ${(error as Error).message}`);
|
|
665
|
-
return null;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* Process agent completion to create artifacts from payload
|
|
671
|
-
* Called after agent run completes successfully
|
|
672
|
-
*/
|
|
673
|
-
private async processAgentCompletionForArtifacts(
|
|
674
|
-
agentRun: AIAgentRunEntityExtended,
|
|
675
|
-
payload: any,
|
|
676
|
-
contextUser: UserInfo,
|
|
677
|
-
conversationDetailId?: string,
|
|
678
|
-
sourceArtifactId?: string
|
|
679
|
-
): Promise<{ artifactId?: string; versionId?: string; versionNumber?: number }> {
|
|
680
|
-
// Validate inputs
|
|
681
|
-
if (!payload || Object.keys(payload).length === 0) {
|
|
682
|
-
LogStatus('No payload to create artifact from');
|
|
683
|
-
return {};
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
if (!conversationDetailId) {
|
|
687
|
-
LogStatus('Skipping artifact creation - no conversationDetailId provided');
|
|
688
|
-
return {};
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// Check agent's ArtifactCreationMode
|
|
692
|
-
await AIEngine.Instance.Config(false, contextUser);
|
|
693
|
-
const agent = AIEngine.Instance.Agents.find(a => a.ID === agentRun.AgentID);
|
|
694
|
-
const creationMode = agent?.ArtifactCreationMode;
|
|
695
|
-
|
|
696
|
-
if (creationMode === 'Never') {
|
|
697
|
-
LogStatus(`Skipping artifact creation - agent "${agent?.Name}" has ArtifactCreationMode='Never'`);
|
|
698
|
-
return {};
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
try {
|
|
702
|
-
const md = new Metadata();
|
|
703
|
-
const JSON_ARTIFACT_TYPE_ID = 'ae674c7e-ea0d-49ea-89e4-0649f5eb20d4';
|
|
704
|
-
|
|
705
|
-
// 1. Determine if creating new artifact or new version
|
|
706
|
-
let artifactId: string;
|
|
707
|
-
let newVersionNumber: number;
|
|
708
|
-
let isNewArtifact = false;
|
|
709
|
-
|
|
710
|
-
// Priority 1: Use explicit source artifact if provided (agent continuity/refinement)
|
|
711
|
-
if (sourceArtifactId) {
|
|
712
|
-
const maxVersion = await this.getMaxVersionForArtifact(sourceArtifactId, contextUser);
|
|
713
|
-
artifactId = sourceArtifactId;
|
|
714
|
-
newVersionNumber = maxVersion + 1;
|
|
715
|
-
LogStatus(`Creating version ${newVersionNumber} of source artifact ${artifactId} (explicit source)`);
|
|
716
|
-
}
|
|
717
|
-
// Priority 2: Try to find previous artifact for this message (fallback)
|
|
718
|
-
else {
|
|
719
|
-
const previousArtifact = await this.findPreviousArtifactForMessage(
|
|
720
|
-
conversationDetailId,
|
|
721
|
-
contextUser
|
|
722
|
-
);
|
|
723
|
-
|
|
724
|
-
if (previousArtifact) {
|
|
725
|
-
// Create new version of existing artifact
|
|
726
|
-
artifactId = previousArtifact.artifactId;
|
|
727
|
-
newVersionNumber = previousArtifact.versionNumber + 1;
|
|
728
|
-
LogStatus(`Creating version ${newVersionNumber} of existing artifact ${artifactId}`);
|
|
729
|
-
} else {
|
|
730
|
-
// Create new artifact header
|
|
731
|
-
const artifact = await md.GetEntityObject<ArtifactEntity>(
|
|
732
|
-
'MJ: Artifacts',
|
|
733
|
-
contextUser
|
|
734
|
-
);
|
|
735
|
-
|
|
736
|
-
// Get agent info for naming and visibility control
|
|
737
|
-
await AIEngine.Instance.Config(false, contextUser);
|
|
738
|
-
const agent = AIEngine.Instance.Agents.find(a => a.ID === agentRun.AgentID);
|
|
739
|
-
const agentName = agent?.Name || 'Agent';
|
|
740
|
-
|
|
741
|
-
artifact.Name = `${agentName} Payload - ${new Date().toLocaleString()}`;
|
|
742
|
-
artifact.Description = `Payload returned by ${agentName}`;
|
|
743
|
-
|
|
744
|
-
// Use agent's DefaultArtifactTypeID if available, otherwise JSON
|
|
745
|
-
const defaultArtifactTypeId = (agent as any)?.DefaultArtifactTypeID;
|
|
746
|
-
artifact.TypeID = defaultArtifactTypeId || JSON_ARTIFACT_TYPE_ID;
|
|
747
|
-
|
|
748
|
-
artifact.UserID = contextUser.ID;
|
|
749
|
-
artifact.EnvironmentID = (contextUser as any).EnvironmentID ||
|
|
750
|
-
'F51358F3-9447-4176-B313-BF8025FD8D09';
|
|
751
|
-
|
|
752
|
-
// Set visibility based on agent's ArtifactCreationMode
|
|
753
|
-
// Will compile after CodeGen adds the new fields
|
|
754
|
-
const creationMode = agent.ArtifactCreationMode;
|
|
755
|
-
if (creationMode === 'System Only') {
|
|
756
|
-
artifact.Visibility = 'System Only';
|
|
757
|
-
LogStatus(`Artifact marked as "System Only" per agent configuration`);
|
|
758
|
-
} else {
|
|
759
|
-
artifact.Visibility = 'Always';
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
if (!(await artifact.Save())) {
|
|
763
|
-
throw new Error('Failed to save artifact');
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
artifactId = artifact.ID;
|
|
767
|
-
newVersionNumber = 1;
|
|
768
|
-
isNewArtifact = true;
|
|
769
|
-
LogStatus(`Created new artifact: ${artifact.Name} (${artifactId})`);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
// 2. Create artifact version with content
|
|
774
|
-
const version = await md.GetEntityObject<ArtifactVersionEntity>(
|
|
775
|
-
'MJ: Artifact Versions',
|
|
776
|
-
contextUser
|
|
777
|
-
);
|
|
778
|
-
version.ArtifactID = artifactId;
|
|
779
|
-
version.VersionNumber = newVersionNumber;
|
|
780
|
-
version.Content = JSON.stringify(payload, null, 2);
|
|
781
|
-
version.UserID = contextUser.ID;
|
|
782
|
-
|
|
783
|
-
if (!(await version.Save())) {
|
|
784
|
-
throw new Error('Failed to save artifact version');
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
LogStatus(`Created artifact version ${newVersionNumber} (${version.ID})`);
|
|
788
|
-
|
|
789
|
-
// If this is the first version of a new artifact, check for extracted Name attribute and update artifact
|
|
790
|
-
if (isNewArtifact && newVersionNumber === 1) {
|
|
791
|
-
const nameAttr = (version as any).Attributes?.find((attr: any) =>
|
|
792
|
-
attr.StandardProperty === 'name' || attr.Name?.toLowerCase() === 'name'
|
|
793
|
-
);
|
|
794
|
-
|
|
795
|
-
// Check for valid name value (not null, not empty, not string "null")
|
|
796
|
-
let extractedName = nameAttr?.Value?.trim();
|
|
797
|
-
if (extractedName && extractedName.toLowerCase() !== 'null') {
|
|
798
|
-
// Strip surrounding quotes (double or single) from start and end
|
|
799
|
-
extractedName = extractedName.replace(/^["']|["']$/g, '');
|
|
800
|
-
|
|
801
|
-
// Load artifact to update with extracted name
|
|
802
|
-
const artifact = await md.GetEntityObject<ArtifactEntity>(
|
|
803
|
-
'MJ: Artifacts',
|
|
804
|
-
contextUser
|
|
805
|
-
);
|
|
806
|
-
|
|
807
|
-
if (!(await artifact.Load(artifactId))) {
|
|
808
|
-
LogError('Failed to reload artifact for name update');
|
|
809
|
-
} else {
|
|
810
|
-
artifact.Name = extractedName;
|
|
811
|
-
if (await artifact.Save()) {
|
|
812
|
-
LogStatus(`✨ Updated artifact name to: ${artifact.Name}`);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
// 3. Create junction record linking artifact to conversation detail
|
|
819
|
-
const junction = await md.GetEntityObject<ConversationDetailArtifactEntity>(
|
|
820
|
-
'MJ: Conversation Detail Artifacts',
|
|
821
|
-
contextUser
|
|
822
|
-
);
|
|
823
|
-
junction.ConversationDetailID = conversationDetailId;
|
|
824
|
-
junction.ArtifactVersionID = version.ID;
|
|
825
|
-
junction.Direction = 'Output';
|
|
826
|
-
|
|
827
|
-
if (!(await junction.Save())) {
|
|
828
|
-
throw new Error('Failed to create artifact-message association');
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
LogStatus(`Linked artifact to conversation detail ${conversationDetailId}`);
|
|
832
|
-
|
|
833
|
-
return {
|
|
834
|
-
artifactId,
|
|
835
|
-
versionId: version.ID,
|
|
836
|
-
versionNumber: newVersionNumber
|
|
837
|
-
};
|
|
838
|
-
} catch (error) {
|
|
839
|
-
LogError(`Failed to process agent completion for artifacts: ${(error as Error).message}`);
|
|
840
|
-
return {};
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
|
|
844
594
|
/**
|
|
845
595
|
* Create a user notification for agent completion with artifact
|
|
846
596
|
* Notification includes navigation link back to the conversation
|