@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.
- 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 +1308 -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 +269 -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 +3660 -3386
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +22009 -20223
- package/dist/generated/generated.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -18
- package/dist/index.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/CreateQueryResolver.d.ts +2 -2
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +12 -12
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/EntityResolver.d.ts +2 -2
- package/dist/resolvers/EntityResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityResolver.js +4 -4
- package/dist/resolvers/EntityResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +2 -2
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +6 -6
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +14 -14
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +0 -2
- package/dist/resolvers/PotentialDuplicateRecordResolver.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 +28 -21
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts +18 -0
- package/dist/resolvers/TaskResolver.d.ts.map +1 -0
- package/dist/resolvers/TaskResolver.js +138 -0
- package/dist/resolvers/TaskResolver.js.map +1 -0
- package/dist/resolvers/UserFavoriteResolver.d.ts +2 -2
- package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +5 -5
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts +2 -2
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +7 -7
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts +2 -2
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +8 -8
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/services/TaskOrchestrator.d.ts +52 -0
- package/dist/services/TaskOrchestrator.d.ts.map +1 -0
- package/dist/services/TaskOrchestrator.js +486 -0
- package/dist/services/TaskOrchestrator.js.map +1 -0
- package/package.json +30 -38
- package/src/agents/skip-agent.ts +1433 -0
- package/src/agents/skip-sdk.ts +541 -0
- package/src/config.ts +3 -2
- package/src/generated/generated.ts +7948 -6811
- package/src/index.ts +7 -21
- package/src/resolvers/AskSkipResolver.ts +32 -10
- package/src/resolvers/ComponentRegistryResolver.ts +133 -4
- package/src/resolvers/CreateQueryResolver.ts +6 -6
- package/src/resolvers/EntityResolver.ts +4 -4
- package/src/resolvers/FileCategoryResolver.ts +2 -2
- package/src/resolvers/FileResolver.ts +12 -12
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +2 -3
- package/src/resolvers/RunAIAgentResolver.ts +23 -10
- package/src/resolvers/RunTemplateResolver.ts +1 -2
- package/src/resolvers/TaskResolver.ts +142 -0
- package/src/resolvers/UserFavoriteResolver.ts +5 -5
- package/src/resolvers/UserResolver.ts +7 -7
- package/src/resolvers/UserViewResolver.ts +8 -8
- package/src/services/TaskOrchestration-Integration.md +188 -0
- package/src/services/TaskOrchestrator.ts +756 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserViewResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/UserViewResolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAA+C,MAAM,wBAAwB,CAAC;AACjG,OAAO,
|
|
1
|
+
{"version":3,"file":"UserViewResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/UserViewResolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAA+C,MAAM,wBAAwB,CAAC;AACjG,OAAO,EAAe,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAKhF,qBACa,gBAAiB,SAAQ,sBAAsB;IAEpD,iBAAiB,CAA2B,MAAM,EAAE,MAAM,EAAS,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,UAAU;IAMzG,0BAA0B,CACJ,MAAM,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EACrC,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,UAAU;IAOzC,gCAAgC,CAA6B,QAAQ,EAAE,MAAM,EAAS,OAAO,EAAE,UAAU;cAS/F,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAOhE,8BAA8B,CAA6B,QAAQ,EAAE,MAAM,EAAS,OAAO,EAAE,UAAU;IAMvG,iBAAiB,CAA0B,EAAE,EAAE,MAAM,EAAS,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,UAAU;CAiB3G;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -11,10 +11,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
import { Arg, Ctx, Int, Query, Resolver } from '@memberjunction/server';
|
|
14
|
-
import {
|
|
14
|
+
import { MJUserView_, MJUserViewResolverBase } from '../generated/generated.js';
|
|
15
15
|
import { UserResolver } from './UserResolver.js';
|
|
16
16
|
import { GetReadOnlyProvider } from '../util.js';
|
|
17
|
-
let UserViewResolver = class UserViewResolver extends
|
|
17
|
+
let UserViewResolver = class UserViewResolver extends MJUserViewResolverBase {
|
|
18
18
|
async UserViewsByUserID(UserID, { providers, userPayload }) {
|
|
19
19
|
const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
|
|
20
20
|
return await this.findBy(provider, 'User Views', { UserID }, userPayload.userRecord);
|
|
@@ -55,7 +55,7 @@ let UserViewResolver = class UserViewResolver extends UserViewResolverBase {
|
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
57
|
__decorate([
|
|
58
|
-
Query(() => [
|
|
58
|
+
Query(() => [MJUserView_]),
|
|
59
59
|
__param(0, Arg('UserID', () => Int)),
|
|
60
60
|
__param(1, Ctx()),
|
|
61
61
|
__metadata("design:type", Function),
|
|
@@ -63,7 +63,7 @@ __decorate([
|
|
|
63
63
|
__metadata("design:returntype", Promise)
|
|
64
64
|
], UserViewResolver.prototype, "UserViewsByUserID", null);
|
|
65
65
|
__decorate([
|
|
66
|
-
Query(() => [
|
|
66
|
+
Query(() => [MJUserView_]),
|
|
67
67
|
__param(0, Arg('UserID', () => Int)),
|
|
68
68
|
__param(1, Arg('EntityID', () => Int)),
|
|
69
69
|
__param(2, Ctx()),
|
|
@@ -72,7 +72,7 @@ __decorate([
|
|
|
72
72
|
__metadata("design:returntype", Promise)
|
|
73
73
|
], UserViewResolver.prototype, "DefaultViewByUserAndEntity", null);
|
|
74
74
|
__decorate([
|
|
75
|
-
Query(() => [
|
|
75
|
+
Query(() => [MJUserView_]),
|
|
76
76
|
__param(0, Arg('EntityID', () => Int)),
|
|
77
77
|
__param(1, Ctx()),
|
|
78
78
|
__metadata("design:type", Function),
|
|
@@ -80,7 +80,7 @@ __decorate([
|
|
|
80
80
|
__metadata("design:returntype", Promise)
|
|
81
81
|
], UserViewResolver.prototype, "CurrentUserDefaultViewByEntityID", null);
|
|
82
82
|
__decorate([
|
|
83
|
-
Query(() => [
|
|
83
|
+
Query(() => [MJUserView_]),
|
|
84
84
|
__param(0, Arg('EntityID', () => Int)),
|
|
85
85
|
__param(1, Ctx()),
|
|
86
86
|
__metadata("design:type", Function),
|
|
@@ -88,7 +88,7 @@ __decorate([
|
|
|
88
88
|
__metadata("design:returntype", Promise)
|
|
89
89
|
], UserViewResolver.prototype, "CurrentUserUserViewsByEntityID", null);
|
|
90
90
|
__decorate([
|
|
91
|
-
Query(() => [
|
|
91
|
+
Query(() => [MJUserView_]),
|
|
92
92
|
__param(0, Arg('ID', () => String)),
|
|
93
93
|
__param(1, Ctx()),
|
|
94
94
|
__metadata("design:type", Function),
|
|
@@ -96,7 +96,7 @@ __decorate([
|
|
|
96
96
|
__metadata("design:returntype", Promise)
|
|
97
97
|
], UserViewResolver.prototype, "UpdateWhereClause", null);
|
|
98
98
|
UserViewResolver = __decorate([
|
|
99
|
-
Resolver(
|
|
99
|
+
Resolver(MJUserView_)
|
|
100
100
|
], UserViewResolver);
|
|
101
101
|
export { UserViewResolver };
|
|
102
102
|
export default UserViewResolver;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserViewResolver.js","sourceRoot":"","sources":["../../src/resolvers/UserViewResolver.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,OAAO,EAAc,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAe,MAAM,wBAAwB,CAAC;AACjG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"UserViewResolver.js","sourceRoot":"","sources":["../../src/resolvers/UserViewResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { UserInfo } from '@memberjunction/core';
|
|
2
|
+
import { PubSubEngine } from 'type-graphql';
|
|
3
|
+
import { UserPayload } from '../types.js';
|
|
4
|
+
export interface TaskDefinition {
|
|
5
|
+
tempId: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
agentName: string;
|
|
9
|
+
dependsOn: string[];
|
|
10
|
+
inputPayload?: any;
|
|
11
|
+
}
|
|
12
|
+
export interface TaskGraphResponse {
|
|
13
|
+
workflowName: string;
|
|
14
|
+
tasks: TaskDefinition[];
|
|
15
|
+
reasoning?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TaskExecutionResult {
|
|
18
|
+
taskId: string;
|
|
19
|
+
success: boolean;
|
|
20
|
+
output?: any;
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class TaskOrchestrator {
|
|
24
|
+
private contextUser;
|
|
25
|
+
private pubSub?;
|
|
26
|
+
private sessionId?;
|
|
27
|
+
private userPayload?;
|
|
28
|
+
private readonly JSON_ARTIFACT_TYPE_ID;
|
|
29
|
+
private taskTypeId;
|
|
30
|
+
constructor(contextUser: UserInfo, pubSub?: PubSubEngine, sessionId?: string, userPayload?: UserPayload);
|
|
31
|
+
private ensureTaskType;
|
|
32
|
+
createTasksFromGraph(taskGraph: TaskGraphResponse, conversationDetailId: string, environmentId: string): Promise<{
|
|
33
|
+
parentTaskId: string;
|
|
34
|
+
taskIdMap: Map<string, string>;
|
|
35
|
+
}>;
|
|
36
|
+
private publishTaskProgress;
|
|
37
|
+
private publishAgentProgress;
|
|
38
|
+
private findAgentByName;
|
|
39
|
+
executeTasksForParent(parentTaskId: string): Promise<TaskExecutionResult[]>;
|
|
40
|
+
private findEligibleTasks;
|
|
41
|
+
private updateParentTaskProgress;
|
|
42
|
+
private completeParentTask;
|
|
43
|
+
private hasIncompleteDependencies;
|
|
44
|
+
private loadTask;
|
|
45
|
+
private executeTask;
|
|
46
|
+
private extractInputPayload;
|
|
47
|
+
private getDependentTaskOutputs;
|
|
48
|
+
private buildConversationMessages;
|
|
49
|
+
private extractAgentOutput;
|
|
50
|
+
private createArtifactFromOutput;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=TaskOrchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TaskOrchestrator.d.ts","sourceRoot":"","sources":["../../src/services/TaskOrchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,QAAQ,EAAuB,MAAM,sBAAsB,CAAC;AAIxF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM1C,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,GAAG,CAAC;CACtB;AAKD,MAAM,WAAW,iBAAiB;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD,qBAAa,gBAAgB;IAOrB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM,CAAC;IACf,OAAO,CAAC,SAAS,CAAC;IAClB,OAAO,CAAC,WAAW,CAAC;IARxB,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA0C;IAEhF,OAAO,CAAC,UAAU,CAAuB;gBAG7B,WAAW,EAAE,QAAQ,EACrB,MAAM,CAAC,EAAE,YAAY,EACrB,SAAS,CAAC,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,WAAW;YAMvB,cAAc;IAuCtB,oBAAoB,CACtB,SAAS,EAAE,iBAAiB,EAC5B,oBAAoB,EAAE,MAAM,EAC5B,aAAa,EAAE,MAAM,GACtB,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IAwGpE,OAAO,CAAC,mBAAmB;IA8B3B,OAAO,CAAC,oBAAoB;YA8Bd,eAAe;IAoBvB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAqDnE,iBAAiB;YA8BjB,wBAAwB;YAiCxB,kBAAkB;YAiBlB,yBAAyB;YA4BzB,QAAQ;YAUR,WAAW;IAsHzB,OAAO,CAAC,mBAAmB;YAiBb,uBAAuB;YAqCvB,yBAAyB;IAsCvC,OAAO,CAAC,kBAAkB;YAkBZ,wBAAwB;CAuEzC"}
|
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
import { Metadata, RunView, LogError, LogStatus } from '@memberjunction/core';
|
|
2
|
+
import { AgentRunner } from '@memberjunction/ai-agents';
|
|
3
|
+
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
|
|
4
|
+
export class TaskOrchestrator {
|
|
5
|
+
contextUser;
|
|
6
|
+
pubSub;
|
|
7
|
+
sessionId;
|
|
8
|
+
userPayload;
|
|
9
|
+
JSON_ARTIFACT_TYPE_ID = 'ae674c7e-ea0d-49ea-89e4-0649f5eb20d4';
|
|
10
|
+
taskTypeId = null;
|
|
11
|
+
constructor(contextUser, pubSub, sessionId, userPayload) {
|
|
12
|
+
this.contextUser = contextUser;
|
|
13
|
+
this.pubSub = pubSub;
|
|
14
|
+
this.sessionId = sessionId;
|
|
15
|
+
this.userPayload = userPayload;
|
|
16
|
+
}
|
|
17
|
+
async ensureTaskType() {
|
|
18
|
+
if (this.taskTypeId) {
|
|
19
|
+
return this.taskTypeId;
|
|
20
|
+
}
|
|
21
|
+
const rv = new RunView();
|
|
22
|
+
const result = await rv.RunView({
|
|
23
|
+
EntityName: 'MJ: Task Types',
|
|
24
|
+
ExtraFilter: `Name='AI Agent Execution'`,
|
|
25
|
+
ResultType: 'entity_object'
|
|
26
|
+
}, this.contextUser);
|
|
27
|
+
if (result.Success && result.Results && result.Results.length > 0) {
|
|
28
|
+
this.taskTypeId = result.Results[0].ID;
|
|
29
|
+
return this.taskTypeId;
|
|
30
|
+
}
|
|
31
|
+
const md = new Metadata();
|
|
32
|
+
const taskType = await md.GetEntityObject('MJ: Task Types', this.contextUser);
|
|
33
|
+
taskType.Name = 'AI Agent Execution';
|
|
34
|
+
taskType.Description = 'Task executed by an AI agent as part of conversation workflow';
|
|
35
|
+
const saved = await taskType.Save();
|
|
36
|
+
if (!saved) {
|
|
37
|
+
throw new Error('Failed to create AI Agent Execution task type');
|
|
38
|
+
}
|
|
39
|
+
this.taskTypeId = taskType.ID;
|
|
40
|
+
return this.taskTypeId;
|
|
41
|
+
}
|
|
42
|
+
async createTasksFromGraph(taskGraph, conversationDetailId, environmentId) {
|
|
43
|
+
const taskTypeId = await this.ensureTaskType();
|
|
44
|
+
const md = new Metadata();
|
|
45
|
+
const tempIdToRealId = new Map();
|
|
46
|
+
const parentTask = await md.GetEntityObject('MJ: Tasks', this.contextUser);
|
|
47
|
+
parentTask.Name = taskGraph.workflowName;
|
|
48
|
+
parentTask.Description = taskGraph.reasoning || 'AI-orchestrated workflow';
|
|
49
|
+
parentTask.TypeID = taskTypeId;
|
|
50
|
+
parentTask.EnvironmentID = environmentId;
|
|
51
|
+
parentTask.ConversationDetailID = conversationDetailId;
|
|
52
|
+
parentTask.Status = 'In Progress';
|
|
53
|
+
parentTask.PercentComplete = 0;
|
|
54
|
+
const parentSaved = await parentTask.Save();
|
|
55
|
+
if (!parentSaved) {
|
|
56
|
+
throw new Error('Failed to create parent workflow task');
|
|
57
|
+
}
|
|
58
|
+
LogStatus(`Created parent workflow task: ${parentTask.Name} (${parentTask.ID})`);
|
|
59
|
+
const seenTempIds = new Set();
|
|
60
|
+
const uniqueTasks = taskGraph.tasks.filter(task => {
|
|
61
|
+
if (seenTempIds.has(task.tempId)) {
|
|
62
|
+
LogError(`Duplicate tempId detected and ignored: ${task.tempId} (${task.name})`);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
seenTempIds.add(task.tempId);
|
|
66
|
+
return true;
|
|
67
|
+
});
|
|
68
|
+
LogStatus(`Creating ${uniqueTasks.length} unique child tasks (${taskGraph.tasks.length - uniqueTasks.length} duplicates filtered)`);
|
|
69
|
+
for (const taskDef of uniqueTasks) {
|
|
70
|
+
const task = await md.GetEntityObject('MJ: Tasks', this.contextUser);
|
|
71
|
+
const agent = await this.findAgentByName(taskDef.agentName);
|
|
72
|
+
if (!agent) {
|
|
73
|
+
LogError(`Agent not found: ${taskDef.agentName}`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
task.Name = taskDef.name;
|
|
77
|
+
task.Description = taskDef.description;
|
|
78
|
+
task.TypeID = taskTypeId;
|
|
79
|
+
task.EnvironmentID = environmentId;
|
|
80
|
+
task.ParentID = parentTask.ID;
|
|
81
|
+
task.ConversationDetailID = conversationDetailId;
|
|
82
|
+
task.AgentID = agent.ID;
|
|
83
|
+
task.Status = 'Pending';
|
|
84
|
+
task.PercentComplete = 0;
|
|
85
|
+
if (taskDef.inputPayload) {
|
|
86
|
+
const metadata = {
|
|
87
|
+
inputPayload: taskDef.inputPayload,
|
|
88
|
+
tempId: taskDef.tempId
|
|
89
|
+
};
|
|
90
|
+
task.Description = `${taskDef.description}\n\n__TASK_METADATA__\n${JSON.stringify(metadata)}`;
|
|
91
|
+
}
|
|
92
|
+
const saved = await task.Save();
|
|
93
|
+
if (saved) {
|
|
94
|
+
tempIdToRealId.set(taskDef.tempId, task.ID);
|
|
95
|
+
LogStatus(`Created child task: ${task.Name} (${task.ID}) under parent ${parentTask.ID}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const taskDef of uniqueTasks) {
|
|
99
|
+
const taskId = tempIdToRealId.get(taskDef.tempId);
|
|
100
|
+
if (!taskId)
|
|
101
|
+
continue;
|
|
102
|
+
for (const dependsOnTempId of taskDef.dependsOn) {
|
|
103
|
+
const dependsOnId = tempIdToRealId.get(dependsOnTempId);
|
|
104
|
+
if (!dependsOnId) {
|
|
105
|
+
LogError(`Dependency not found: ${dependsOnTempId}`);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const dependency = await md.GetEntityObject('MJ: Task Dependencies', this.contextUser);
|
|
109
|
+
dependency.TaskID = taskId;
|
|
110
|
+
dependency.DependsOnTaskID = dependsOnId;
|
|
111
|
+
dependency.DependencyType = 'Prerequisite';
|
|
112
|
+
await dependency.Save();
|
|
113
|
+
LogStatus(`Created dependency: Task ${taskId} depends on ${dependsOnId}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
parentTaskId: parentTask.ID,
|
|
118
|
+
taskIdMap: tempIdToRealId
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
publishTaskProgress(taskName, message, percentComplete) {
|
|
122
|
+
if (!this.pubSub || !this.sessionId || !this.userPayload) {
|
|
123
|
+
LogStatus(`⚠️ PubSub not available for progress updates (pubSub: ${!!this.pubSub}, sessionId: ${!!this.sessionId}, userPayload: ${!!this.userPayload})`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const payload = {
|
|
127
|
+
message: JSON.stringify({
|
|
128
|
+
resolver: 'TaskOrchestrator',
|
|
129
|
+
type: 'TaskProgress',
|
|
130
|
+
status: 'ok',
|
|
131
|
+
data: {
|
|
132
|
+
taskName,
|
|
133
|
+
message,
|
|
134
|
+
percentComplete,
|
|
135
|
+
timestamp: new Date()
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
sessionId: this.userPayload.sessionId
|
|
139
|
+
};
|
|
140
|
+
LogStatus(`📡 Publishing task progress: ${taskName} - ${message} (${percentComplete}%) to session ${this.userPayload.sessionId}`);
|
|
141
|
+
this.pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, payload);
|
|
142
|
+
LogStatus(`[Task: ${taskName}] ${message} (${percentComplete}%)`);
|
|
143
|
+
}
|
|
144
|
+
publishAgentProgress(taskName, agentStep, agentMessage) {
|
|
145
|
+
if (!this.pubSub || !this.sessionId || !this.userPayload) {
|
|
146
|
+
LogStatus(`⚠️ PubSub not available for agent progress (pubSub: ${!!this.pubSub}, sessionId: ${!!this.sessionId}, userPayload: ${!!this.userPayload})`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const payload = {
|
|
150
|
+
message: JSON.stringify({
|
|
151
|
+
resolver: 'TaskOrchestrator',
|
|
152
|
+
type: 'AgentProgress',
|
|
153
|
+
status: 'ok',
|
|
154
|
+
data: {
|
|
155
|
+
taskName,
|
|
156
|
+
agentStep,
|
|
157
|
+
agentMessage,
|
|
158
|
+
timestamp: new Date()
|
|
159
|
+
}
|
|
160
|
+
}),
|
|
161
|
+
sessionId: this.userPayload.sessionId
|
|
162
|
+
};
|
|
163
|
+
LogStatus(`📡 Publishing agent progress: ${taskName} → ${agentStep} to session ${this.userPayload.sessionId}`);
|
|
164
|
+
this.pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, payload);
|
|
165
|
+
LogStatus(`[Task: ${taskName}] → ${agentStep}: ${agentMessage}`);
|
|
166
|
+
}
|
|
167
|
+
async findAgentByName(agentName) {
|
|
168
|
+
const rv = new RunView();
|
|
169
|
+
const result = await rv.RunView({
|
|
170
|
+
EntityName: 'AI Agents',
|
|
171
|
+
ExtraFilter: `Name='${agentName.replace(/'/g, "''")}'`,
|
|
172
|
+
ResultType: 'entity_object'
|
|
173
|
+
}, this.contextUser);
|
|
174
|
+
if (result.Success && result.Results && result.Results.length > 0) {
|
|
175
|
+
return result.Results[0];
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
async executeTasksForParent(parentTaskId) {
|
|
180
|
+
const results = [];
|
|
181
|
+
let hasMore = true;
|
|
182
|
+
const md = new Metadata();
|
|
183
|
+
const parentTask = await md.GetEntityObject('MJ: Tasks', this.contextUser);
|
|
184
|
+
await parentTask.Load(parentTaskId);
|
|
185
|
+
this.publishTaskProgress(parentTask.Name, 'Starting workflow execution', 0);
|
|
186
|
+
while (hasMore) {
|
|
187
|
+
const eligibleTasks = await this.findEligibleTasks(parentTaskId);
|
|
188
|
+
if (eligibleTasks.length === 0) {
|
|
189
|
+
hasMore = false;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
for (const task of eligibleTasks) {
|
|
193
|
+
this.publishTaskProgress(task.Name, 'Starting task', 0);
|
|
194
|
+
const result = await this.executeTask(task);
|
|
195
|
+
results.push(result);
|
|
196
|
+
if (result.success) {
|
|
197
|
+
this.publishTaskProgress(task.Name, 'Task completed successfully', 100);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
this.publishTaskProgress(task.Name, `Task failed: ${result.error}`, 100);
|
|
201
|
+
}
|
|
202
|
+
await this.updateParentTaskProgress(parentTaskId);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
await this.completeParentTask(parentTaskId);
|
|
206
|
+
this.publishTaskProgress(parentTask.Name, 'Workflow completed', 100);
|
|
207
|
+
return results;
|
|
208
|
+
}
|
|
209
|
+
async findEligibleTasks(parentTaskId) {
|
|
210
|
+
const rv = new RunView();
|
|
211
|
+
const tasksResult = await rv.RunView({
|
|
212
|
+
EntityName: 'MJ: Tasks',
|
|
213
|
+
ExtraFilter: `ParentID='${parentTaskId}' AND Status='Pending'`,
|
|
214
|
+
ResultType: 'entity_object'
|
|
215
|
+
}, this.contextUser);
|
|
216
|
+
if (!tasksResult.Success || !tasksResult.Results) {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
const eligibleTasks = [];
|
|
220
|
+
for (const task of tasksResult.Results) {
|
|
221
|
+
const hasIncompleteDeps = await this.hasIncompleteDependencies(task.ID);
|
|
222
|
+
if (!hasIncompleteDeps) {
|
|
223
|
+
eligibleTasks.push(task);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return eligibleTasks;
|
|
227
|
+
}
|
|
228
|
+
async updateParentTaskProgress(parentTaskId) {
|
|
229
|
+
const md = new Metadata();
|
|
230
|
+
const parentTask = await md.GetEntityObject('MJ: Tasks', this.contextUser);
|
|
231
|
+
const loaded = await parentTask.Load(parentTaskId);
|
|
232
|
+
if (!loaded)
|
|
233
|
+
return;
|
|
234
|
+
const rv = new RunView();
|
|
235
|
+
const childrenResult = await rv.RunView({
|
|
236
|
+
EntityName: 'MJ: Tasks',
|
|
237
|
+
ExtraFilter: `ParentID='${parentTaskId}'`,
|
|
238
|
+
ResultType: 'entity_object'
|
|
239
|
+
}, this.contextUser);
|
|
240
|
+
if (!childrenResult.Success || !childrenResult.Results || childrenResult.Results.length === 0) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const children = childrenResult.Results;
|
|
244
|
+
const completedCount = children.filter(t => t.Status === 'Complete').length;
|
|
245
|
+
const totalCount = children.length;
|
|
246
|
+
parentTask.PercentComplete = Math.round((completedCount / totalCount) * 100);
|
|
247
|
+
await parentTask.Save();
|
|
248
|
+
LogStatus(`Parent task ${parentTask.Name} is ${parentTask.PercentComplete}% complete (${completedCount}/${totalCount} tasks)`);
|
|
249
|
+
}
|
|
250
|
+
async completeParentTask(parentTaskId) {
|
|
251
|
+
const md = new Metadata();
|
|
252
|
+
const parentTask = await md.GetEntityObject('MJ: Tasks', this.contextUser);
|
|
253
|
+
const loaded = await parentTask.Load(parentTaskId);
|
|
254
|
+
if (!loaded)
|
|
255
|
+
return;
|
|
256
|
+
parentTask.Status = 'Complete';
|
|
257
|
+
parentTask.PercentComplete = 100;
|
|
258
|
+
parentTask.CompletedAt = new Date();
|
|
259
|
+
await parentTask.Save();
|
|
260
|
+
LogStatus(`Parent workflow task completed: ${parentTask.Name}`);
|
|
261
|
+
}
|
|
262
|
+
async hasIncompleteDependencies(taskId) {
|
|
263
|
+
const rv = new RunView();
|
|
264
|
+
const depsResult = await rv.RunView({
|
|
265
|
+
EntityName: 'MJ: Task Dependencies',
|
|
266
|
+
ExtraFilter: `TaskID='${taskId}'`,
|
|
267
|
+
ResultType: 'entity_object'
|
|
268
|
+
}, this.contextUser);
|
|
269
|
+
if (!depsResult.Success || !depsResult.Results || depsResult.Results.length === 0) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
for (const dep of depsResult.Results) {
|
|
273
|
+
const dependsOnTask = await this.loadTask(dep.DependsOnTaskID);
|
|
274
|
+
if (dependsOnTask && dependsOnTask.Status !== 'Complete') {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
async loadTask(taskId) {
|
|
281
|
+
const md = new Metadata();
|
|
282
|
+
const task = await md.GetEntityObject('MJ: Tasks', this.contextUser);
|
|
283
|
+
const loaded = await task.Load(taskId);
|
|
284
|
+
return loaded ? task : null;
|
|
285
|
+
}
|
|
286
|
+
async executeTask(task) {
|
|
287
|
+
try {
|
|
288
|
+
LogStatus(`Executing task: ${task.Name} (${task.ID})`);
|
|
289
|
+
task.Status = 'In Progress';
|
|
290
|
+
task.StartedAt = new Date();
|
|
291
|
+
await task.Save();
|
|
292
|
+
const md = new Metadata();
|
|
293
|
+
const agentEntity = await md.GetEntityObject('AI Agents', this.contextUser);
|
|
294
|
+
const loaded = await agentEntity.Load(task.AgentID);
|
|
295
|
+
if (!loaded) {
|
|
296
|
+
throw new Error(`Agent with ID ${task.AgentID} not found`);
|
|
297
|
+
}
|
|
298
|
+
const messages = await this.buildConversationMessages(task);
|
|
299
|
+
const onProgress = (progress) => {
|
|
300
|
+
this.publishAgentProgress(task.Name, progress.step || 'processing', progress.message || '');
|
|
301
|
+
};
|
|
302
|
+
const agentRunner = new AgentRunner();
|
|
303
|
+
const agentResult = await agentRunner.RunAgent({
|
|
304
|
+
agent: agentEntity,
|
|
305
|
+
conversationMessages: messages,
|
|
306
|
+
contextUser: this.contextUser,
|
|
307
|
+
conversationDetailId: task.ConversationDetailID || undefined,
|
|
308
|
+
onProgress: onProgress
|
|
309
|
+
});
|
|
310
|
+
if (agentResult.success) {
|
|
311
|
+
const output = this.extractAgentOutput(agentResult);
|
|
312
|
+
const outputMetadata = {
|
|
313
|
+
outputType: output.type,
|
|
314
|
+
output: output.content,
|
|
315
|
+
agentRunId: agentResult.agentRun?.ID
|
|
316
|
+
};
|
|
317
|
+
task.Status = 'Complete';
|
|
318
|
+
task.CompletedAt = new Date();
|
|
319
|
+
task.PercentComplete = 100;
|
|
320
|
+
task.Description = `${task.Description}\n\n__TASK_OUTPUT__\n${JSON.stringify(outputMetadata)}`;
|
|
321
|
+
await task.Save();
|
|
322
|
+
LogStatus(`Task completed: ${task.Name} (output type: ${output.type})`);
|
|
323
|
+
let conversationDetailId = task.ConversationDetailID;
|
|
324
|
+
if (!conversationDetailId && task.ParentID) {
|
|
325
|
+
const parentTask = await this.loadTask(task.ParentID);
|
|
326
|
+
conversationDetailId = parentTask?.ConversationDetailID || null;
|
|
327
|
+
}
|
|
328
|
+
if (conversationDetailId && output.content) {
|
|
329
|
+
await this.createArtifactFromOutput(output, conversationDetailId, agentEntity, task.Name);
|
|
330
|
+
}
|
|
331
|
+
else if (!conversationDetailId) {
|
|
332
|
+
LogError(`Cannot create artifact: No conversation detail ID found for task ${task.ID}`);
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
taskId: task.ID,
|
|
336
|
+
success: true,
|
|
337
|
+
output: output.content
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
task.Status = 'Failed';
|
|
342
|
+
task.CompletedAt = new Date();
|
|
343
|
+
await task.Save();
|
|
344
|
+
const errorMsg = agentResult.agentRun?.ErrorMessage || 'Agent execution failed';
|
|
345
|
+
LogError(`Task failed: ${task.Name} - ${errorMsg}`);
|
|
346
|
+
return {
|
|
347
|
+
taskId: task.ID,
|
|
348
|
+
success: false,
|
|
349
|
+
error: errorMsg
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
LogError(error);
|
|
355
|
+
task.Status = 'Failed';
|
|
356
|
+
task.CompletedAt = new Date();
|
|
357
|
+
await task.Save();
|
|
358
|
+
return {
|
|
359
|
+
taskId: task.ID,
|
|
360
|
+
success: false,
|
|
361
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
extractInputPayload(task) {
|
|
366
|
+
if (!task.Description)
|
|
367
|
+
return null;
|
|
368
|
+
const metadataMatch = task.Description.match(/__TASK_METADATA__\n(.+?)(?:\n\n|$)/s);
|
|
369
|
+
if (!metadataMatch)
|
|
370
|
+
return null;
|
|
371
|
+
try {
|
|
372
|
+
const metadata = JSON.parse(metadataMatch[1]);
|
|
373
|
+
return metadata.inputPayload || null;
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
async getDependentTaskOutputs(taskId) {
|
|
380
|
+
const outputs = new Map();
|
|
381
|
+
const rv = new RunView();
|
|
382
|
+
const depsResult = await rv.RunView({
|
|
383
|
+
EntityName: 'MJ: Task Dependencies',
|
|
384
|
+
ExtraFilter: `TaskID='${taskId}'`,
|
|
385
|
+
ResultType: 'entity_object'
|
|
386
|
+
}, this.contextUser);
|
|
387
|
+
if (!depsResult.Success || !depsResult.Results) {
|
|
388
|
+
return outputs;
|
|
389
|
+
}
|
|
390
|
+
for (const dep of depsResult.Results) {
|
|
391
|
+
const dependsOnTask = await this.loadTask(dep.DependsOnTaskID);
|
|
392
|
+
if (!dependsOnTask || !dependsOnTask.Description)
|
|
393
|
+
continue;
|
|
394
|
+
const outputMatch = dependsOnTask.Description.match(/__TASK_OUTPUT__\n(.+?)$/s);
|
|
395
|
+
if (outputMatch) {
|
|
396
|
+
try {
|
|
397
|
+
const outputMetadata = JSON.parse(outputMatch[1]);
|
|
398
|
+
outputs.set(dep.DependsOnTaskID, outputMetadata.output);
|
|
399
|
+
}
|
|
400
|
+
catch (e) {
|
|
401
|
+
LogError(`Failed to parse output for task ${dep.DependsOnTaskID}: ${e}`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return outputs;
|
|
406
|
+
}
|
|
407
|
+
async buildConversationMessages(task) {
|
|
408
|
+
const messages = [];
|
|
409
|
+
let userContent = task.Description || task.Name;
|
|
410
|
+
const inputPayload = this.extractInputPayload(task);
|
|
411
|
+
const dependentOutputs = await this.getDependentTaskOutputs(task.ID);
|
|
412
|
+
if (dependentOutputs.size > 0) {
|
|
413
|
+
userContent += '\n\n## Results from Dependent Tasks:\n\n';
|
|
414
|
+
for (const [taskId, outputData] of dependentOutputs.entries()) {
|
|
415
|
+
const depTask = await this.loadTask(taskId);
|
|
416
|
+
const taskName = depTask?.Name || taskId;
|
|
417
|
+
userContent += `### ${taskName}\n\`\`\`json\n${JSON.stringify(outputData, null, 2)}\n\`\`\`\n\n`;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (inputPayload) {
|
|
421
|
+
userContent += '\n\n## Task Input:\n\`\`\`json\n' + JSON.stringify(inputPayload, null, 2) + '\n\`\`\`';
|
|
422
|
+
}
|
|
423
|
+
messages.push({
|
|
424
|
+
role: 'user',
|
|
425
|
+
content: userContent
|
|
426
|
+
});
|
|
427
|
+
return messages;
|
|
428
|
+
}
|
|
429
|
+
extractAgentOutput(agentResult) {
|
|
430
|
+
if (agentResult.agentRun?.Message) {
|
|
431
|
+
return { type: 'message', content: agentResult.agentRun.Message };
|
|
432
|
+
}
|
|
433
|
+
if (agentResult.payload && Object.keys(agentResult.payload).length > 0) {
|
|
434
|
+
return { type: 'payload', content: agentResult.payload };
|
|
435
|
+
}
|
|
436
|
+
return { type: 'message', content: '' };
|
|
437
|
+
}
|
|
438
|
+
async createArtifactFromOutput(output, conversationDetailId, agent, taskName) {
|
|
439
|
+
try {
|
|
440
|
+
const md = new Metadata();
|
|
441
|
+
const artifact = await md.GetEntityObject('MJ: Artifacts', this.contextUser);
|
|
442
|
+
artifact.Name = `${agent.Name} - ${taskName} - ${new Date().toLocaleString()}`;
|
|
443
|
+
artifact.Description = `Artifact generated by ${agent.Name} for task: ${taskName} (${output.type})`;
|
|
444
|
+
const defaultArtifactTypeId = agent.DefaultArtifactTypeID;
|
|
445
|
+
artifact.TypeID = defaultArtifactTypeId || this.JSON_ARTIFACT_TYPE_ID;
|
|
446
|
+
artifact.UserID = this.contextUser.ID;
|
|
447
|
+
artifact.EnvironmentID = this.contextUser.EnvironmentID || 'F51358F3-9447-4176-B313-BF8025FD8D09';
|
|
448
|
+
const artifactSaved = await artifact.Save();
|
|
449
|
+
if (!artifactSaved) {
|
|
450
|
+
LogError('Failed to save artifact');
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
LogStatus(`Created artifact: ${artifact.Name} (${artifact.ID})`);
|
|
454
|
+
const version = await md.GetEntityObject('MJ: Artifact Versions', this.contextUser);
|
|
455
|
+
version.ArtifactID = artifact.ID;
|
|
456
|
+
version.VersionNumber = 1;
|
|
457
|
+
if (output.type === 'message') {
|
|
458
|
+
version.Content = output.content;
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
version.Content = JSON.stringify(output.content, null, 2);
|
|
462
|
+
}
|
|
463
|
+
version.UserID = this.contextUser.ID;
|
|
464
|
+
const versionSaved = await version.Save();
|
|
465
|
+
if (!versionSaved) {
|
|
466
|
+
LogError('Failed to save artifact version');
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
LogStatus(`Created artifact version: ${version.ID}`);
|
|
470
|
+
const junction = await md.GetEntityObject('MJ: Conversation Detail Artifacts', this.contextUser);
|
|
471
|
+
junction.ConversationDetailID = conversationDetailId;
|
|
472
|
+
junction.ArtifactVersionID = version.ID;
|
|
473
|
+
junction.Direction = 'Output';
|
|
474
|
+
const junctionSaved = await junction.Save();
|
|
475
|
+
if (!junctionSaved) {
|
|
476
|
+
LogError('Failed to create artifact-conversation association');
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
LogStatus(`Linked artifact ${artifact.ID} to conversation detail ${conversationDetailId}`);
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
LogError(`Error creating artifact from output: ${error}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
//# sourceMappingURL=TaskOrchestrator.js.map
|