@memberjunction/server 5.28.0 → 5.30.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/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +63 -70
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/config.d.ts +151 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -1
- package/dist/generated/generated.d.ts +452 -6
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2788 -303
- package/dist/generated/generated.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/resolvers/FeedbackResolver.d.ts +150 -0
- package/dist/resolvers/FeedbackResolver.d.ts.map +1 -0
- package/dist/resolvers/FeedbackResolver.js +876 -0
- package/dist/resolvers/FeedbackResolver.js.map +1 -0
- package/dist/resolvers/FileResolver.d.ts +27 -0
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +32 -3
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +100 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +532 -41
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +77 -0
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +300 -1
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +87 -32
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +20 -12
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +20 -9
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +153 -116
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/services/TaskOrchestrator.d.ts.map +1 -1
- package/dist/services/TaskOrchestrator.js +78 -79
- package/dist/services/TaskOrchestrator.js.map +1 -1
- package/package.json +68 -66
- package/src/auth/newUsers.ts +65 -74
- package/src/config.ts +19 -0
- package/src/generated/generated.ts +1753 -40
- package/src/index.ts +1 -0
- package/src/resolvers/FeedbackResolver.ts +940 -0
- package/src/resolvers/FileResolver.ts +33 -4
- package/src/resolvers/IntegrationDiscoveryResolver.ts +543 -43
- package/src/resolvers/MCPResolver.ts +297 -1
- package/src/resolvers/RunAIAgentResolver.ts +89 -32
- package/src/resolvers/SyncDataResolver.ts +24 -14
- package/src/resolvers/SyncRolesUsersResolver.ts +177 -141
- package/src/services/TaskOrchestrator.ts +86 -93
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Metadata, RunView, UserInfo, LogError, LogStatus } from '@memberjunction/core';
|
|
1
|
+
import { DatabaseProviderBase, Metadata, RunView, UserInfo, LogError, LogStatus } from '@memberjunction/core';
|
|
2
2
|
import { MJTaskEntity, MJTaskDependencyEntity, MJTaskTypeEntity, MJConversationDetailEntity, MJArtifactEntity, MJArtifactVersionEntity, MJConversationDetailArtifactEntity, MJUserNotificationEntity } from '@memberjunction/core-entities';
|
|
3
3
|
import { AgentRunner } from '@memberjunction/ai-agents';
|
|
4
4
|
import { ChatMessageRole } from '@memberjunction/ai';
|
|
@@ -107,24 +107,18 @@ export class TaskOrchestrator {
|
|
|
107
107
|
const md = new Metadata();
|
|
108
108
|
const tempIdToRealId = new Map<string, string>();
|
|
109
109
|
|
|
110
|
-
//
|
|
110
|
+
// Build the parent task, deduplicate the incoming task defs, and resolve agents
|
|
111
|
+
// BEFORE opening the transaction so all preparatory work (cache lookups, agent
|
|
112
|
+
// resolution RunViews) happens outside the critical section.
|
|
111
113
|
const parentTask = await md.GetEntityObject<MJTaskEntity>('MJ: Tasks', this.contextUser);
|
|
112
114
|
parentTask.Name = taskGraph.workflowName;
|
|
113
115
|
parentTask.Description = taskGraph.reasoning || 'AI-orchestrated workflow';
|
|
114
116
|
parentTask.TypeID = taskTypeId;
|
|
115
117
|
parentTask.EnvironmentID = environmentId;
|
|
116
|
-
parentTask.ConversationDetailID = conversationDetailId;
|
|
117
|
-
parentTask.Status = 'In Progress';
|
|
118
|
+
parentTask.ConversationDetailID = conversationDetailId;
|
|
119
|
+
parentTask.Status = 'In Progress';
|
|
118
120
|
parentTask.PercentComplete = 0;
|
|
119
121
|
|
|
120
|
-
const parentSaved = await parentTask.Save();
|
|
121
|
-
if (!parentSaved) {
|
|
122
|
-
throw new Error('Failed to create parent workflow task');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
LogStatus(`Created parent workflow task: ${parentTask.Name} (${parentTask.ID})`);
|
|
126
|
-
|
|
127
|
-
// Deduplicate tasks by tempId (LLM sometimes returns duplicates)
|
|
128
122
|
const seenTempIds = new Set<string>();
|
|
129
123
|
const uniqueTasks = taskGraph.tasks.filter(task => {
|
|
130
124
|
if (seenTempIds.has(task.tempId)) {
|
|
@@ -135,66 +129,81 @@ export class TaskOrchestrator {
|
|
|
135
129
|
return true;
|
|
136
130
|
});
|
|
137
131
|
|
|
138
|
-
LogStatus(`
|
|
132
|
+
LogStatus(`Preparing parent + ${uniqueTasks.length} unique child tasks (${taskGraph.tasks.length - uniqueTasks.length} duplicates filtered)`);
|
|
139
133
|
|
|
140
|
-
|
|
134
|
+
const resolvedTasks: Array<{ def: TaskDefinition; agentId: string }> = [];
|
|
141
135
|
for (const taskDef of uniqueTasks) {
|
|
142
|
-
const task = await md.GetEntityObject<MJTaskEntity>('MJ: Tasks', this.contextUser);
|
|
143
|
-
|
|
144
|
-
// Find agent by name
|
|
145
136
|
const agent = await this.findAgentByName(taskDef.agentName);
|
|
146
137
|
if (!agent) {
|
|
147
138
|
LogError(`Agent not found: ${taskDef.agentName}`);
|
|
148
139
|
continue;
|
|
149
140
|
}
|
|
141
|
+
resolvedTasks.push({ def: taskDef, agentId: agent.ID });
|
|
142
|
+
}
|
|
150
143
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
task.AgentID = agent.ID;
|
|
158
|
-
task.Status = 'Pending';
|
|
159
|
-
task.PercentComplete = 0;
|
|
160
|
-
|
|
161
|
-
// Store input payload if provided
|
|
162
|
-
if (taskDef.inputPayload) {
|
|
163
|
-
const metadata = {
|
|
164
|
-
inputPayload: taskDef.inputPayload,
|
|
165
|
-
tempId: taskDef.tempId
|
|
166
|
-
};
|
|
167
|
-
// Store in a well-known format at the end of description
|
|
168
|
-
task.Description = `${taskDef.description}\n\n__TASK_METADATA__\n${JSON.stringify(metadata)}`;
|
|
144
|
+
// Persist parent + children + dependency graph in one transaction
|
|
145
|
+
const provider = Metadata.Provider as DatabaseProviderBase;
|
|
146
|
+
await provider.BeginTransaction();
|
|
147
|
+
try {
|
|
148
|
+
if (!await parentTask.Save()) {
|
|
149
|
+
throw new Error(`Failed to create parent workflow task: ${parentTask.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
169
150
|
}
|
|
151
|
+
LogStatus(`Created parent workflow task: ${parentTask.Name} (${parentTask.ID})`);
|
|
152
|
+
|
|
153
|
+
for (const { def, agentId } of resolvedTasks) {
|
|
154
|
+
const task = await md.GetEntityObject<MJTaskEntity>('MJ: Tasks', this.contextUser);
|
|
155
|
+
task.Name = def.name;
|
|
156
|
+
task.Description = def.description;
|
|
157
|
+
task.TypeID = taskTypeId;
|
|
158
|
+
task.EnvironmentID = environmentId;
|
|
159
|
+
task.ParentID = parentTask.ID;
|
|
160
|
+
task.ConversationDetailID = conversationDetailId;
|
|
161
|
+
task.AgentID = agentId;
|
|
162
|
+
task.Status = 'Pending';
|
|
163
|
+
task.PercentComplete = 0;
|
|
164
|
+
|
|
165
|
+
if (def.inputPayload) {
|
|
166
|
+
const metadata = {
|
|
167
|
+
inputPayload: def.inputPayload,
|
|
168
|
+
tempId: def.tempId
|
|
169
|
+
};
|
|
170
|
+
task.Description = `${def.description}\n\n__TASK_METADATA__\n${JSON.stringify(metadata)}`;
|
|
171
|
+
}
|
|
170
172
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
if (!await task.Save()) {
|
|
174
|
+
throw new Error(`Failed to create child task '${def.name}': ${task.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
175
|
+
}
|
|
176
|
+
tempIdToRealId.set(def.tempId, task.ID);
|
|
174
177
|
LogStatus(`Created child task: ${task.Name} (${task.ID}) under parent ${parentTask.ID}`);
|
|
175
178
|
}
|
|
176
|
-
}
|
|
177
179
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
180
|
+
for (const { def } of resolvedTasks) {
|
|
181
|
+
const taskId = tempIdToRealId.get(def.tempId);
|
|
182
|
+
if (!taskId) continue;
|
|
183
|
+
|
|
184
|
+
for (const dependsOnTempId of def.dependsOn) {
|
|
185
|
+
const dependsOnId = tempIdToRealId.get(dependsOnTempId);
|
|
186
|
+
if (!dependsOnId) {
|
|
187
|
+
LogError(`Dependency not found: ${dependsOnTempId}`);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const dependency = await md.GetEntityObject<MJTaskDependencyEntity>('MJ: Task Dependencies', this.contextUser);
|
|
192
|
+
dependency.TaskID = taskId;
|
|
193
|
+
dependency.DependsOnTaskID = dependsOnId;
|
|
194
|
+
dependency.DependencyType = 'Prerequisite';
|
|
195
|
+
|
|
196
|
+
if (!await dependency.Save()) {
|
|
197
|
+
throw new Error(`Failed to create task dependency (${taskId} -> ${dependsOnId}): ${dependency.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
198
|
+
}
|
|
199
|
+
LogStatus(`Created dependency: Task ${taskId} depends on ${dependsOnId}`);
|
|
188
200
|
}
|
|
189
|
-
|
|
190
|
-
const dependency = await md.GetEntityObject<MJTaskDependencyEntity>('MJ: Task Dependencies', this.contextUser);
|
|
191
|
-
dependency.TaskID = taskId;
|
|
192
|
-
dependency.DependsOnTaskID = dependsOnId;
|
|
193
|
-
dependency.DependencyType = 'Prerequisite';
|
|
194
|
-
|
|
195
|
-
await dependency.Save();
|
|
196
|
-
LogStatus(`Created dependency: Task ${taskId} depends on ${dependsOnId}`);
|
|
197
201
|
}
|
|
202
|
+
|
|
203
|
+
await provider.CommitTransaction();
|
|
204
|
+
} catch (txErr) {
|
|
205
|
+
await provider.RollbackTransaction();
|
|
206
|
+
throw txErr;
|
|
198
207
|
}
|
|
199
208
|
|
|
200
209
|
return {
|
|
@@ -698,23 +707,22 @@ export class TaskOrchestrator {
|
|
|
698
707
|
agent: MJAIAgentEntityExtended,
|
|
699
708
|
taskName: string
|
|
700
709
|
): Promise<void> {
|
|
701
|
-
|
|
702
|
-
|
|
710
|
+
const md = new Metadata();
|
|
711
|
+
const provider = Metadata.Provider as DatabaseProviderBase;
|
|
703
712
|
|
|
713
|
+
await provider.BeginTransaction();
|
|
714
|
+
try {
|
|
704
715
|
// Create Artifact header
|
|
705
716
|
const artifact = await md.GetEntityObject<MJArtifactEntity>('MJ: Artifacts', this.contextUser);
|
|
706
717
|
artifact.Name = `${agent.Name} - ${taskName} - ${new Date().toLocaleString()}`;
|
|
707
718
|
artifact.Description = `Artifact generated by ${agent.Name} for task: ${taskName} (${output.type})`;
|
|
708
719
|
|
|
709
|
-
// Use agent's DefaultArtifactTypeID if available, otherwise fall back to JSON
|
|
710
720
|
const defaultArtifactTypeId = (agent as any).DefaultArtifactTypeID;
|
|
711
721
|
artifact.TypeID = defaultArtifactTypeId || this.JSON_ARTIFACT_TYPE_ID;
|
|
712
722
|
|
|
713
723
|
artifact.UserID = this.contextUser.ID;
|
|
714
724
|
artifact.EnvironmentID = (this.contextUser as any).EnvironmentID || 'F51358F3-9447-4176-B313-BF8025FD8D09';
|
|
715
725
|
|
|
716
|
-
// Set visibility based on agent's ArtifactCreationMode
|
|
717
|
-
// Will compile after CodeGen adds the new fields
|
|
718
726
|
const creationMode = agent.ArtifactCreationMode;
|
|
719
727
|
if (creationMode === 'System Only') {
|
|
720
728
|
artifact.Visibility = 'System Only';
|
|
@@ -723,51 +731,36 @@ export class TaskOrchestrator {
|
|
|
723
731
|
artifact.Visibility = 'Always';
|
|
724
732
|
}
|
|
725
733
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
LogError('Failed to save artifact');
|
|
729
|
-
return;
|
|
734
|
+
if (!await artifact.Save()) {
|
|
735
|
+
throw new Error(`Failed to save artifact: ${artifact.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
730
736
|
}
|
|
731
|
-
|
|
732
737
|
LogStatus(`Created artifact: ${artifact.Name} (${artifact.ID})`);
|
|
733
738
|
|
|
734
739
|
// Create Artifact Version with content
|
|
735
740
|
const version = await md.GetEntityObject<MJArtifactVersionEntity>('MJ: Artifact Versions', this.contextUser);
|
|
736
741
|
version.ArtifactID = artifact.ID;
|
|
737
742
|
version.VersionNumber = 1;
|
|
738
|
-
|
|
739
|
-
// Store content based on output type
|
|
740
|
-
if (output.type === 'message') {
|
|
741
|
-
version.Content = output.content;
|
|
742
|
-
} else {
|
|
743
|
-
version.Content = JSON.stringify(output.content, null, 2);
|
|
744
|
-
}
|
|
745
|
-
|
|
743
|
+
version.Content = output.type === 'message' ? output.content : JSON.stringify(output.content, null, 2);
|
|
746
744
|
version.UserID = this.contextUser.ID;
|
|
747
745
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
LogError('Failed to save artifact version');
|
|
751
|
-
return;
|
|
746
|
+
if (!await version.Save()) {
|
|
747
|
+
throw new Error(`Failed to save artifact version: ${version.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
752
748
|
}
|
|
753
|
-
|
|
754
749
|
LogStatus(`Created artifact version: ${version.ID}`);
|
|
755
750
|
|
|
756
|
-
//
|
|
751
|
+
// If extraction produced a better name, update the artifact in the same transaction
|
|
757
752
|
const nameAttr = (version as any).Attributes?.find((attr: any) =>
|
|
758
753
|
attr.StandardProperty === 'name' || attr.Name?.toLowerCase() === 'name'
|
|
759
754
|
);
|
|
760
755
|
|
|
761
|
-
// Check for valid name value (not null, not empty, not string "null")
|
|
762
756
|
let extractedName = nameAttr?.Value?.trim();
|
|
763
757
|
if (extractedName && extractedName.toLowerCase() !== 'null') {
|
|
764
|
-
// Strip surrounding quotes (double or single) from start and end
|
|
765
758
|
extractedName = extractedName.replace(/^["']|["']$/g, '');
|
|
766
|
-
|
|
767
759
|
artifact.Name = extractedName;
|
|
768
|
-
if (await artifact.Save()) {
|
|
769
|
-
|
|
760
|
+
if (!await artifact.Save()) {
|
|
761
|
+
throw new Error(`Failed to update artifact name: ${artifact.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
770
762
|
}
|
|
763
|
+
LogStatus(`✨ Updated artifact name to: ${artifact.Name}`);
|
|
771
764
|
}
|
|
772
765
|
|
|
773
766
|
// Create M2M relationship linking artifact to conversation detail
|
|
@@ -777,17 +770,17 @@ export class TaskOrchestrator {
|
|
|
777
770
|
);
|
|
778
771
|
junction.ConversationDetailID = conversationDetailId;
|
|
779
772
|
junction.ArtifactVersionID = version.ID;
|
|
780
|
-
junction.Direction = 'Output';
|
|
773
|
+
junction.Direction = 'Output';
|
|
781
774
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
LogError('Failed to create artifact-conversation association');
|
|
785
|
-
return;
|
|
775
|
+
if (!await junction.Save()) {
|
|
776
|
+
throw new Error(`Failed to create artifact-conversation association: ${junction.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
786
777
|
}
|
|
787
|
-
|
|
788
778
|
LogStatus(`Linked artifact ${artifact.ID} to conversation detail ${conversationDetailId}`);
|
|
779
|
+
|
|
780
|
+
await provider.CommitTransaction();
|
|
789
781
|
} catch (error) {
|
|
790
|
-
|
|
782
|
+
await provider.RollbackTransaction();
|
|
783
|
+
LogError(`Error creating artifact from output — all changes rolled back: ${error}`);
|
|
791
784
|
}
|
|
792
785
|
}
|
|
793
786
|
|