@yrpri/api 9.0.99 → 9.0.101
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/agents/assistants/baseAssistant.js +24 -9
- package/agents/assistants/modes/agentDirectConnection.js +2 -17
- package/agents/assistants/modes/agentSelectionMode.js +5 -8
- package/agents/assistants/modes/tools/agentConnectionTools.js +326 -0
- package/agents/assistants/modes/tools/agentTools.js +3 -1
- package/agents/assistants/modes/tools/loginTools.js +1 -1
- package/agents/assistants/modes/tools/models/subscriptions.js +23 -4
- package/agents/assistants/modes/tools/navigationTools.js +95 -21
- package/agents/assistants/modes/tools/subscriptionTools.js +1 -4
- package/agents/assistants/modes/tools/workflowConversationTools.js +326 -0
- package/agents/assistants/modes/tools/workflowConverstationTools.js +112 -0
- package/agents/assistants/modes/tools/workflowTools.js +112 -0
- package/agents/assistants/voiceAssistant.js +3 -3
- package/agents/controllers/assistantsController.js +60 -2
- package/agents/managers/newAiModelSetup.js +63 -0
- package/agents/managers/notificationAgentQueueManager.js +6 -1
- package/agents/managers/workflowConversationManager.js +79 -0
- package/agents/managers/workflowManager.js +76 -0
- package/agents/models/agentProduct.js +37 -24
- package/agents/models/agentProductRun.js +9 -0
- package/agents/models/testData/setupEvolyAgentProductConfig.js +41 -40
- package/agents/models/workflow.js +53 -0
- package/agents/models/workflowConversation.js +53 -0
- package/agents/models/workflowConverstation.js +53 -0
- package/controllers/users.cjs +1 -0
- package/migrations/zzzzzzz_create_trees.cjs +81 -0
- package/package.json +1 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { BaseAssistantTools } from "./baseTools.js";
|
|
2
|
+
export class WorkflowTools extends BaseAssistantTools {
|
|
3
|
+
constructor(assistant) {
|
|
4
|
+
super(assistant);
|
|
5
|
+
}
|
|
6
|
+
get show_running_workflow_conversations() {
|
|
7
|
+
return {
|
|
8
|
+
name: "show_running_workflow_conversations",
|
|
9
|
+
description: "Display running workflow conversations",
|
|
10
|
+
type: "function",
|
|
11
|
+
parameters: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {},
|
|
14
|
+
required: []
|
|
15
|
+
},
|
|
16
|
+
handler: this.showRunningWorkflowsHandler.bind(this)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async showRunningWorkflowsHandler(params) {
|
|
20
|
+
params = this.assistant.getCleanedParams(params);
|
|
21
|
+
console.log(`handler: show_running_workflows: ${JSON.stringify(params, null, 2)}`);
|
|
22
|
+
try {
|
|
23
|
+
const html = `<yp-workflow-widget-small running="true"></yp-workflow-widget-small>`;
|
|
24
|
+
return {
|
|
25
|
+
success: true,
|
|
26
|
+
html,
|
|
27
|
+
uniqueToken: "runningWorkflows",
|
|
28
|
+
data: { message: "Running workflows displayed successfully" },
|
|
29
|
+
metadata: { timestamp: new Date().toISOString() }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
const errorMessage = error instanceof Error ? error.message : "Error displaying running workflows";
|
|
34
|
+
console.error(`Error in show_running_workflows: ${errorMessage}`);
|
|
35
|
+
return {
|
|
36
|
+
success: false,
|
|
37
|
+
error: errorMessage
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
get show_all_workflow_conversations() {
|
|
42
|
+
return {
|
|
43
|
+
name: "show_all_workflow_conversations",
|
|
44
|
+
description: "Display all workflow conversations",
|
|
45
|
+
type: "function",
|
|
46
|
+
parameters: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {},
|
|
49
|
+
required: []
|
|
50
|
+
},
|
|
51
|
+
handler: this.showAllWorkflowsHandler.bind(this)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
async showAllWorkflowsHandler(params) {
|
|
55
|
+
params = this.assistant.getCleanedParams(params);
|
|
56
|
+
console.log(`handler: show_all_workflows: ${JSON.stringify(params, null, 2)}`);
|
|
57
|
+
try {
|
|
58
|
+
const html = `<yp-workflow-widget-small all="true"></yp-workflow-widget-small>`;
|
|
59
|
+
return {
|
|
60
|
+
success: true,
|
|
61
|
+
html,
|
|
62
|
+
uniqueToken: "allWorkflows",
|
|
63
|
+
data: { message: "All workflows displayed successfully" },
|
|
64
|
+
metadata: { timestamp: new Date().toISOString() }
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const errorMessage = error instanceof Error ? error.message : "Error displaying all workflows";
|
|
69
|
+
console.error(`Error in show_all_workflows: ${errorMessage}`);
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: errorMessage
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
get connect_to_workflow_conversation() {
|
|
77
|
+
return {
|
|
78
|
+
name: "connect_to_workflow_conversation",
|
|
79
|
+
description: "Connect to an existing workflow conversation",
|
|
80
|
+
type: "function",
|
|
81
|
+
parameters: {
|
|
82
|
+
type: "object",
|
|
83
|
+
properties: {
|
|
84
|
+
workflowId: { type: "number" }
|
|
85
|
+
},
|
|
86
|
+
required: ["workflowId"]
|
|
87
|
+
},
|
|
88
|
+
handler: this.connectToWorkflowHandler.bind(this)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async connectToWorkflowHandler(params) {
|
|
92
|
+
params = this.assistant.getCleanedParams(params);
|
|
93
|
+
console.log(`handler: connect_to_workflow: ${JSON.stringify(params, null, 2)}`);
|
|
94
|
+
try {
|
|
95
|
+
const { workflowId } = params;
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
data: { message: `Connected to workflow ${workflowId} successfully` },
|
|
99
|
+
uniqueToken: `connectWorkflow_${workflowId}`,
|
|
100
|
+
metadata: { timestamp: new Date().toISOString() }
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const errorMessage = error instanceof Error ? error.message : "Error connecting to workflow conversation";
|
|
105
|
+
console.error(`Error in connect_to_workflow_conversation: ${errorMessage}`);
|
|
106
|
+
return {
|
|
107
|
+
success: false,
|
|
108
|
+
error: errorMessage
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -82,7 +82,7 @@ export class YpBaseChatBotWithVoice extends YpBaseChatBot {
|
|
|
82
82
|
throw new Error("No subscription plan found");
|
|
83
83
|
}
|
|
84
84
|
if (subscriptionPlan?.AgentProduct.name) {
|
|
85
|
-
this.exitMessageFromDirectAgentConversation = `Welcome the user back from their conversation with the ${subscriptionPlan.AgentProduct.name}. (it happened on a seperate channel). Now help the user with agent selection
|
|
85
|
+
this.exitMessageFromDirectAgentConversation = `Welcome the user back from their conversation with the ${subscriptionPlan.AgentProduct.name}. (it happened on a seperate channel). Now help the user with agent selection`;
|
|
86
86
|
}
|
|
87
87
|
this.sendToClient("assistant", "", "clear_audio_buffer");
|
|
88
88
|
if (this.directAgentVoiceConnection) {
|
|
@@ -132,7 +132,7 @@ export class YpBaseChatBotWithVoice extends YpBaseChatBot {
|
|
|
132
132
|
this.directAgentVoiceConnection = undefined;
|
|
133
133
|
this.parentAssistant.memory.chatLog.push({
|
|
134
134
|
sender: "user",
|
|
135
|
-
message: "Thank you for the information, I would now like to speak to the main assistant about selecting agents
|
|
135
|
+
message: "Thank you for the information, I would now like to speak to the main assistant about selecting agents",
|
|
136
136
|
});
|
|
137
137
|
await this.parentAssistant.saveMemory();
|
|
138
138
|
}
|
|
@@ -189,7 +189,7 @@ export class YpBaseChatBotWithVoice extends YpBaseChatBot {
|
|
|
189
189
|
await this.handleSpeechStopped();
|
|
190
190
|
break;
|
|
191
191
|
case "response.cancelled":
|
|
192
|
-
console.log("
|
|
192
|
+
console.log("response.cancelled");
|
|
193
193
|
this.isWaitingOnCancelResponseCompleted = false;
|
|
194
194
|
break;
|
|
195
195
|
case "conversation.item.input_audio_transcription.completed":
|
|
@@ -14,6 +14,7 @@ import { YpDiscount } from "../models/discount.js";
|
|
|
14
14
|
import { sequelize } from "@policysynth/agents/dbModels/index.js";
|
|
15
15
|
import { NotificationAgentQueueManager } from "../managers/notificationAgentQueueManager.js";
|
|
16
16
|
import { AgentQueueManager } from "@policysynth/agents/operations/agentQueueManager.js";
|
|
17
|
+
import { WorkflowConversationManager } from "../managers/workflowConversationManager.js";
|
|
17
18
|
const models = {
|
|
18
19
|
YpAgentProduct,
|
|
19
20
|
YpAgentProductBundle,
|
|
@@ -65,7 +66,7 @@ export class AssistantController {
|
|
|
65
66
|
}
|
|
66
67
|
const markdownContent = match[1];
|
|
67
68
|
const htmlContent = await marked(markdownContent);
|
|
68
|
-
const docxBuffer = await HTMLtoDOCX(htmlContent);
|
|
69
|
+
const docxBuffer = (await HTMLtoDOCX(htmlContent));
|
|
69
70
|
console.debug(`docxBuffer: ${docxBuffer.length}`);
|
|
70
71
|
res.setHeader("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
|
71
72
|
res.setHeader("Content-disposition", 'attachment; filename="converted.docx"');
|
|
@@ -121,7 +122,7 @@ export class AssistantController {
|
|
|
121
122
|
const subscription = await YpSubscription.findOne({
|
|
122
123
|
where: {
|
|
123
124
|
id: subscriptionId,
|
|
124
|
-
user_id: req.user.id
|
|
125
|
+
user_id: req.user.id,
|
|
125
126
|
},
|
|
126
127
|
});
|
|
127
128
|
if (!subscription) {
|
|
@@ -335,8 +336,62 @@ export class AssistantController {
|
|
|
335
336
|
res.send({});
|
|
336
337
|
}
|
|
337
338
|
};
|
|
339
|
+
// New API endpoints for workflow management
|
|
340
|
+
this.getRunningWorkflowConversations = async (req, res) => {
|
|
341
|
+
if (!req.user || !req.user.id) {
|
|
342
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
const workflows = await this.workflowConversationManager.getRunningWorkflowConversationsForUser(req.user.id);
|
|
346
|
+
res.status(200).json({
|
|
347
|
+
success: true,
|
|
348
|
+
data: { workflows },
|
|
349
|
+
message: "Running workflows retrieved successfully",
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
console.error("Error retrieving running workflows:", error);
|
|
354
|
+
res.status(500).json({ error: error.message });
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
this.getAllWorkflowConversations = async (req, res) => {
|
|
358
|
+
if (!req.user || !req.user.id) {
|
|
359
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
360
|
+
}
|
|
361
|
+
try {
|
|
362
|
+
const workflows = await this.workflowConversationManager.getWorkflowConversationsForUser(req.user.id);
|
|
363
|
+
res.status(200).json({
|
|
364
|
+
success: true,
|
|
365
|
+
data: { workflows },
|
|
366
|
+
message: "All workflows retrieved successfully",
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
console.error("Error retrieving all workflows:", error);
|
|
371
|
+
res.status(500).json({ error: error.message });
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
this.connectToWorkflowConversation = async (req, res) => {
|
|
375
|
+
if (!req.user || !req.user.id) {
|
|
376
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
const { workflowConversationId, connectionData } = req.body;
|
|
380
|
+
const updatedWorkflowConversation = await this.workflowConversationManager.connectToWorkflowConversation(workflowConversationId, connectionData || {});
|
|
381
|
+
res.status(200).json({
|
|
382
|
+
success: true,
|
|
383
|
+
data: updatedWorkflowConversation,
|
|
384
|
+
message: `Connected to workflow conversation ${workflowConversationId} successfully`,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
console.error("Error connecting to workflow conversation:", error);
|
|
389
|
+
res.status(500).json({ error: error.message });
|
|
390
|
+
}
|
|
391
|
+
};
|
|
338
392
|
this.wsClients = wsClients;
|
|
339
393
|
this.agentQueueManager = new AgentQueueManager();
|
|
394
|
+
this.workflowConversationManager = new WorkflowConversationManager();
|
|
340
395
|
this.initializeRoutes();
|
|
341
396
|
this.initializeModels();
|
|
342
397
|
}
|
|
@@ -355,6 +410,9 @@ export class AssistantController {
|
|
|
355
410
|
this.router.post("/:groupId/:agentId/stopCurrentWorkflowStep", this.stopCurrentWorkflowStep.bind(this));
|
|
356
411
|
this.router.put("/:groupId/:agentId/:runId/advanceOrStopWorkflow", this.advanceOrStopCurrentWorkflowStep.bind(this));
|
|
357
412
|
this.router.get("/:groupId/:agentId/getDocxReport", auth.can("view domain"), this.getDocxReport.bind(this));
|
|
413
|
+
this.router.get("/:domainId/workflowConversations/running", auth.can("view domain"), this.getRunningWorkflowConversations.bind(this));
|
|
414
|
+
this.router.get("/:domainId/workflowConversations/all", auth.can("view domain"), this.getAllWorkflowConversations.bind(this));
|
|
415
|
+
this.router.put("/:domainId/workflowConversations/connect", auth.can("view domain"), this.connectToWorkflowConversation.bind(this));
|
|
358
416
|
}
|
|
359
417
|
async getLastStatusMessageFromDB(agentId) {
|
|
360
418
|
const status = await this.agentQueueManager.getAgentStatus(agentId);
|
|
@@ -84,6 +84,37 @@ export class NewAiModelSetup {
|
|
|
84
84
|
console.log("Anthropic model already exists: Anthropic Sonnet 3.5");
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
+
static async seedAnthropic37Models(userId) {
|
|
88
|
+
const anthropicSonnet = await PsAiModel.findOne({
|
|
89
|
+
where: { name: "Anthropic Sonnet 3.7" },
|
|
90
|
+
});
|
|
91
|
+
const anthropicSonnetConfig = {
|
|
92
|
+
type: PsAiModelType.TextReasoning,
|
|
93
|
+
modelSize: PsAiModelSize.Medium,
|
|
94
|
+
provider: "anthropic",
|
|
95
|
+
prices: {
|
|
96
|
+
costInTokensPerMillion: 3,
|
|
97
|
+
costOutTokensPerMillion: 15,
|
|
98
|
+
currency: "USD",
|
|
99
|
+
},
|
|
100
|
+
maxTokensOut: 8000,
|
|
101
|
+
defaultTemperature: 0.7,
|
|
102
|
+
model: "claude-3-7-sonnet-20250219",
|
|
103
|
+
active: true,
|
|
104
|
+
};
|
|
105
|
+
if (!anthropicSonnet) {
|
|
106
|
+
const createdModel = await PsAiModel.create({
|
|
107
|
+
name: "Anthropic Sonnet 3.7",
|
|
108
|
+
organization_id: 1,
|
|
109
|
+
user_id: userId,
|
|
110
|
+
configuration: anthropicSonnetConfig,
|
|
111
|
+
});
|
|
112
|
+
console.log("Created Anthropic model:", createdModel);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.log("Anthropic model already exists: Anthropic Sonnet 3.7");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
87
118
|
/**
|
|
88
119
|
* Seeds OpenAI models.
|
|
89
120
|
* This currently creates several models including GPT-4o, GPT-4o Mini, o1 Mini,
|
|
@@ -276,6 +307,35 @@ export class NewAiModelSetup {
|
|
|
276
307
|
else {
|
|
277
308
|
console.log("OpenAI model already exists: o3 mini");
|
|
278
309
|
}
|
|
310
|
+
const openAiGpt45 = await PsAiModel.findOne({
|
|
311
|
+
where: { name: "GPT-4.5 Preview" },
|
|
312
|
+
});
|
|
313
|
+
const openAiGpt45Config = {
|
|
314
|
+
type: PsAiModelType.Text,
|
|
315
|
+
modelSize: PsAiModelSize.Large,
|
|
316
|
+
provider: "openai",
|
|
317
|
+
prices: {
|
|
318
|
+
costInTokensPerMillion: 75,
|
|
319
|
+
costOutTokensPerMillion: 150,
|
|
320
|
+
currency: "USD",
|
|
321
|
+
},
|
|
322
|
+
maxTokensOut: 100000,
|
|
323
|
+
defaultTemperature: 0.7,
|
|
324
|
+
model: "gpt-4.5-preview",
|
|
325
|
+
active: true,
|
|
326
|
+
};
|
|
327
|
+
if (!openAiGpt45) {
|
|
328
|
+
await PsAiModel.create({
|
|
329
|
+
name: "GPT-4.5 Preview",
|
|
330
|
+
organization_id: 1,
|
|
331
|
+
user_id: userId,
|
|
332
|
+
configuration: openAiGpt45Config,
|
|
333
|
+
});
|
|
334
|
+
console.log("Created OpenAI model: GPT-4.5 Preview");
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
console.log("OpenAI model already exists: GPT-4.5 Preview updating");
|
|
338
|
+
}
|
|
279
339
|
}
|
|
280
340
|
/**
|
|
281
341
|
* Seeds Google models.
|
|
@@ -380,6 +440,7 @@ export class NewAiModelSetup {
|
|
|
380
440
|
static async seedAiModels(userId) {
|
|
381
441
|
try {
|
|
382
442
|
await NewAiModelSetup.seedAnthropicModels(userId);
|
|
443
|
+
await NewAiModelSetup.seedAnthropic37Models(userId);
|
|
383
444
|
await NewAiModelSetup.seedOpenAiModels(userId);
|
|
384
445
|
await NewAiModelSetup.seedGoogleModels(userId);
|
|
385
446
|
// Optionally, seed the top-level agent class if it does not exist.
|
|
@@ -461,8 +522,10 @@ export class NewAiModelSetup {
|
|
|
461
522
|
// Explicitly type envKey as a key of apiKeys
|
|
462
523
|
const modelsMapping = [
|
|
463
524
|
{ name: "Anthropic Sonnet 3.5", envKey: "ANTHROPIC_CLAUDE_API_KEY" },
|
|
525
|
+
{ name: "Anthropic Sonnet 3.7", envKey: "ANTHROPIC_CLAUDE_API_KEY" },
|
|
464
526
|
{ name: "GPT-4o", envKey: "OPENAI_API_KEY" },
|
|
465
527
|
{ name: "GPT-4o Mini", envKey: "OPENAI_API_KEY" },
|
|
528
|
+
{ name: "GPT-4.5 Preview", envKey: "OPENAI_API_KEY" },
|
|
466
529
|
{ name: "o1 Preview", envKey: "OPENAI_API_KEY" },
|
|
467
530
|
{ name: "o1 Mini", envKey: "OPENAI_API_KEY" },
|
|
468
531
|
{ name: "Gemini 1.5 Pro 2", envKey: "GEMINI_API_KEY" },
|
|
@@ -27,13 +27,18 @@ export class NotificationAgentQueueManager extends AgentQueueManager {
|
|
|
27
27
|
console.log("NotificationAgentQueueManager: Sending notification", agentRunId, updatedWorkflow);
|
|
28
28
|
const wsClient = this.wsClients.get(wsClientId);
|
|
29
29
|
if (wsClient) {
|
|
30
|
+
const currentWorkflowStep = updatedWorkflow?.steps[updatedWorkflow?.currentStepIndex];
|
|
30
31
|
wsClient.send(JSON.stringify({
|
|
31
32
|
type: "updated_workflow",
|
|
32
33
|
action,
|
|
33
34
|
status,
|
|
34
35
|
result,
|
|
35
36
|
agentRunId,
|
|
36
|
-
updatedWorkflow: {
|
|
37
|
+
updatedWorkflow: {
|
|
38
|
+
workflow: updatedWorkflow,
|
|
39
|
+
status: status,
|
|
40
|
+
currentWorkflowStep,
|
|
41
|
+
},
|
|
37
42
|
}));
|
|
38
43
|
}
|
|
39
44
|
else {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { YpWorkflowConversation } from "../models/workflowConversation.js";
|
|
2
|
+
export class WorkflowConversationManager {
|
|
3
|
+
constructor() { }
|
|
4
|
+
async createWorkflowConversation(data) {
|
|
5
|
+
try {
|
|
6
|
+
const workflow = await YpWorkflowConversation.create({
|
|
7
|
+
agentProductId: data.agentProductId,
|
|
8
|
+
userId: data.userId || null,
|
|
9
|
+
configuration: data.configuration || {},
|
|
10
|
+
});
|
|
11
|
+
return workflow;
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
throw new Error(`Error creating workflow conversation: ${error.message}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async getWorkflowConversation(workflowConversationId) {
|
|
18
|
+
try {
|
|
19
|
+
const workflowConversation = await YpWorkflowConversation.findByPk(workflowConversationId);
|
|
20
|
+
return workflowConversation;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw new Error(`Error retrieving workflow conversation: ${error.message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async updateWorkflowConversation(workflowConversationId, updates) {
|
|
27
|
+
try {
|
|
28
|
+
const workflowConversation = await YpWorkflowConversation.findByPk(workflowConversationId);
|
|
29
|
+
if (!workflowConversation) {
|
|
30
|
+
throw new Error("Workflow conversation not found");
|
|
31
|
+
}
|
|
32
|
+
Object.assign(workflowConversation, updates);
|
|
33
|
+
await workflowConversation.save();
|
|
34
|
+
return workflowConversation;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw new Error(`Error updating workflow conversation: ${error.message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async connectToWorkflowConversation(workflowConversationId, connectionData) {
|
|
41
|
+
try {
|
|
42
|
+
const workflowConversation = await YpWorkflowConversation.findByPk(workflowConversationId);
|
|
43
|
+
if (!workflowConversation) {
|
|
44
|
+
throw new Error("Workflow conversation not found");
|
|
45
|
+
}
|
|
46
|
+
workflowConversation.configuration = {
|
|
47
|
+
...workflowConversation.configuration,
|
|
48
|
+
...connectionData,
|
|
49
|
+
};
|
|
50
|
+
await workflowConversation.save();
|
|
51
|
+
return workflowConversation;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new Error(`Error connecting to workflow: ${error.message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async getWorkflowConversationsForUser(userId) {
|
|
58
|
+
try {
|
|
59
|
+
const workflowConversations = await YpWorkflowConversation.findAll({ where: { userId } });
|
|
60
|
+
return workflowConversations;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw new Error(`Error retrieving workflow conversations for user ${userId}: ${error.message}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async getRunningWorkflowConversationsForUser(userId) {
|
|
67
|
+
try {
|
|
68
|
+
const allWorkflowConversations = await this.getWorkflowConversationsForUser(userId);
|
|
69
|
+
const runningWorkflowConversations = allWorkflowConversations.filter((workflowConversation) => {
|
|
70
|
+
return (workflowConversation.configuration &&
|
|
71
|
+
workflowConversation.configuration.running === true);
|
|
72
|
+
});
|
|
73
|
+
return runningWorkflowConversations;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new Error(`Error retrieving running workflows for user ${userId}: ${error.message}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { YpWorkflowConversation } from "../models/workflowConverstation.js";
|
|
2
|
+
export class WorkflowManager {
|
|
3
|
+
constructor() { }
|
|
4
|
+
async createWorkflow(data) {
|
|
5
|
+
try {
|
|
6
|
+
const workflow = await YpWorkflowConversation.create({
|
|
7
|
+
agentProductId: data.agentProductId,
|
|
8
|
+
userId: data.userId || null,
|
|
9
|
+
configuration: data.configuration || {},
|
|
10
|
+
});
|
|
11
|
+
return workflow;
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
throw new Error(`Error creating workflow: ${error.message}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async getWorkflow(workflowId) {
|
|
18
|
+
try {
|
|
19
|
+
const workflow = await YpWorkflowConversation.findByPk(workflowId);
|
|
20
|
+
return workflow;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw new Error(`Error retrieving workflow: ${error.message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async updateWorkflow(workflowId, updates) {
|
|
27
|
+
try {
|
|
28
|
+
const workflow = await YpWorkflowConversation.findByPk(workflowId);
|
|
29
|
+
if (!workflow) {
|
|
30
|
+
throw new Error("Workflow not found");
|
|
31
|
+
}
|
|
32
|
+
Object.assign(workflow, updates);
|
|
33
|
+
await workflow.save();
|
|
34
|
+
return workflow;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw new Error(`Error updating workflow: ${error.message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async connectToWorkflow(workflowId, connectionData) {
|
|
41
|
+
try {
|
|
42
|
+
const workflow = await YpWorkflowConversation.findByPk(workflowId);
|
|
43
|
+
if (!workflow) {
|
|
44
|
+
throw new Error("Workflow not found");
|
|
45
|
+
}
|
|
46
|
+
workflow.configuration = { ...workflow.configuration, ...connectionData };
|
|
47
|
+
await workflow.save();
|
|
48
|
+
return workflow;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
throw new Error(`Error connecting to workflow: ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async getWorkflowsForUser(userId) {
|
|
55
|
+
try {
|
|
56
|
+
const workflows = await YpWorkflowConversation.findAll({ where: { userId } });
|
|
57
|
+
return workflows;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new Error(`Error retrieving workflows for user ${userId}: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async getRunningWorkflowsForUser(userId) {
|
|
64
|
+
try {
|
|
65
|
+
const allWorkflows = await this.getWorkflowsForUser(userId);
|
|
66
|
+
const runningWorkflows = allWorkflows.filter((workflow) => {
|
|
67
|
+
return (workflow.configuration &&
|
|
68
|
+
workflow.configuration.running === true);
|
|
69
|
+
});
|
|
70
|
+
return runningWorkflows;
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw new Error(`Error retrieving running workflows for user ${userId}: ${error.message}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -33,9 +33,13 @@ YpAgentProduct.init({
|
|
|
33
33
|
type: DataTypes.INTEGER,
|
|
34
34
|
allowNull: false,
|
|
35
35
|
},
|
|
36
|
+
parent_agent_product_id: {
|
|
37
|
+
type: DataTypes.INTEGER,
|
|
38
|
+
allowNull: true,
|
|
39
|
+
},
|
|
36
40
|
configuration: {
|
|
37
41
|
type: DataTypes.JSONB,
|
|
38
|
-
allowNull: false
|
|
42
|
+
allowNull: false,
|
|
39
43
|
},
|
|
40
44
|
status: {
|
|
41
45
|
type: DataTypes.JSONB,
|
|
@@ -54,12 +58,13 @@ YpAgentProduct.init({
|
|
|
54
58
|
},
|
|
55
59
|
}, {
|
|
56
60
|
sequelize,
|
|
57
|
-
tableName:
|
|
61
|
+
tableName: "agent_products",
|
|
58
62
|
indexes: [
|
|
59
|
-
{ fields: [
|
|
60
|
-
{ fields: [
|
|
61
|
-
{ fields: [
|
|
62
|
-
{ fields: [
|
|
63
|
+
{ fields: ["uuid"], unique: true },
|
|
64
|
+
{ fields: ["user_id"] },
|
|
65
|
+
{ fields: ["group_id"] },
|
|
66
|
+
{ fields: ["domain_id"] },
|
|
67
|
+
{ fields: ["parent_agent_product_id"] },
|
|
63
68
|
],
|
|
64
69
|
timestamps: true,
|
|
65
70
|
underscored: true,
|
|
@@ -67,37 +72,45 @@ YpAgentProduct.init({
|
|
|
67
72
|
YpAgentProduct.associate = (models) => {
|
|
68
73
|
console.log(`YpAgentProduct.associate`);
|
|
69
74
|
YpAgentProduct.belongsTo(models.YpSubscriptionUser, {
|
|
70
|
-
foreignKey:
|
|
71
|
-
as:
|
|
75
|
+
foreignKey: "user_id",
|
|
76
|
+
as: "User",
|
|
72
77
|
});
|
|
73
78
|
YpAgentProduct.belongsTo(models.Group, {
|
|
74
|
-
foreignKey:
|
|
75
|
-
as:
|
|
79
|
+
foreignKey: "group_id",
|
|
80
|
+
as: "Group",
|
|
76
81
|
});
|
|
77
82
|
YpAgentProduct.hasOne(models.YpAgentProductBundle, {
|
|
78
|
-
foreignKey:
|
|
79
|
-
as:
|
|
83
|
+
foreignKey: "agent_bundle_id",
|
|
84
|
+
as: "AgentBundle",
|
|
80
85
|
});
|
|
81
86
|
YpAgentProduct.hasMany(models.YpAgentProductBoosterPurchase, {
|
|
82
|
-
foreignKey:
|
|
83
|
-
as:
|
|
87
|
+
foreignKey: "agent_product_id",
|
|
88
|
+
as: "BoosterPurchases",
|
|
84
89
|
});
|
|
85
90
|
YpAgentProduct.hasMany(models.YpSubscription, {
|
|
86
|
-
foreignKey:
|
|
87
|
-
as:
|
|
91
|
+
foreignKey: "agent_product_id",
|
|
92
|
+
as: "Subscriptions",
|
|
88
93
|
});
|
|
89
94
|
YpAgentProduct.hasMany(models.YpSubscriptionPlan, {
|
|
90
|
-
foreignKey:
|
|
91
|
-
as:
|
|
95
|
+
foreignKey: "agent_product_id",
|
|
96
|
+
as: "SubscriptionPlans",
|
|
92
97
|
});
|
|
93
98
|
YpAgentProduct.hasMany(models.YpAgentProductRun, {
|
|
94
|
-
foreignKey:
|
|
95
|
-
as:
|
|
99
|
+
foreignKey: "agent_product_id",
|
|
100
|
+
as: "Runs",
|
|
96
101
|
});
|
|
97
102
|
YpAgentProduct.belongsToMany(models.YpAgentProductBundle, {
|
|
98
|
-
through:
|
|
99
|
-
foreignKey:
|
|
100
|
-
otherKey:
|
|
101
|
-
as:
|
|
103
|
+
through: "agent_product_bundles_products",
|
|
104
|
+
foreignKey: "agent_product_id",
|
|
105
|
+
otherKey: "agent_product_bundle_id",
|
|
106
|
+
as: "AgentBundles",
|
|
107
|
+
});
|
|
108
|
+
YpAgentProduct.belongsTo(YpAgentProduct, {
|
|
109
|
+
as: "ParentAgentProduct",
|
|
110
|
+
foreignKey: "parent_agent_product_id",
|
|
111
|
+
});
|
|
112
|
+
YpAgentProduct.hasMany(YpAgentProduct, {
|
|
113
|
+
as: "ChildAgentProducts",
|
|
114
|
+
foreignKey: "parent_agent_product_id",
|
|
102
115
|
});
|
|
103
116
|
};
|
|
@@ -10,6 +10,7 @@ YpAgentProductRun.init({
|
|
|
10
10
|
start_time: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
11
11
|
end_time: { type: DataTypes.DATE, allowNull: true },
|
|
12
12
|
duration: { type: DataTypes.INTEGER, allowNull: true },
|
|
13
|
+
parent_agent_product_run_id: { type: DataTypes.INTEGER, allowNull: true },
|
|
13
14
|
status: {
|
|
14
15
|
type: DataTypes.STRING,
|
|
15
16
|
allowNull: false,
|
|
@@ -40,4 +41,12 @@ YpAgentProductRun.associate = (models) => {
|
|
|
40
41
|
foreignKey: 'subscription_id',
|
|
41
42
|
as: 'Subscription',
|
|
42
43
|
});
|
|
44
|
+
YpAgentProductRun.belongsTo(models.YpAgentProductRun, {
|
|
45
|
+
foreignKey: 'parent_agent_product_run_id',
|
|
46
|
+
as: 'ParentAgentProduct',
|
|
47
|
+
});
|
|
48
|
+
YpAgentProductRun.hasMany(models.YpAgentProductRun, {
|
|
49
|
+
foreignKey: 'parent_agent_product_run_id',
|
|
50
|
+
as: 'ChildAgentProducts',
|
|
51
|
+
});
|
|
43
52
|
};
|