@yrpri/api 9.0.80 → 9.0.81

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.
@@ -104,6 +104,9 @@ const renderTemplateWithLocals = (templatePath, locals, done) => {
104
104
  });
105
105
  };
106
106
  const translateSubject = function (subjectHash) {
107
+ if (typeof subjectHash === 'string') {
108
+ return i18n.t(subjectHash);
109
+ }
107
110
  var subject = i18n.t(subjectHash.translateToken);
108
111
  if (subjectHash.contentName) {
109
112
  subject += ": " + subjectHash.contentName;
@@ -315,7 +315,7 @@ export class AgentTools extends BaseAssistantTools {
315
315
  get showConfigurationWidget() {
316
316
  return {
317
317
  name: "show_configuration_widget_if_needed_or_user_asks_to_show_it",
318
- description: "Show the configuration widget for the current agent, this is needed before running the agent workflow",
318
+ description: "Show the configuration widget for the current agent. The user needs to fill out the configuration before running the agent workflow to make sure to offer it to the user.",
319
319
  type: "function",
320
320
  parameters: {
321
321
  type: "object",
@@ -386,7 +386,7 @@ export class AgentTools extends BaseAssistantTools {
386
386
  success: true,
387
387
  clientEvents: [clientEvent],
388
388
  data: {
389
- message: "Submitted configuration for the current agent successfully",
389
+ message: "Submitted configuration for the current agent successfully now offer the user to start the agent workflow run",
390
390
  },
391
391
  };
392
392
  }
@@ -45,6 +45,7 @@ export class SubscriptionModels {
45
45
  return {
46
46
  availablePlans: availablePlans.map((plan) => ({
47
47
  subscriptionPlanId: plan.id,
48
+ type: plan.configuration?.type || "coming_soon",
48
49
  name: plan.AgentProduct?.configuration?.displayName || "No name available",
49
50
  description: plan.AgentProduct?.description || "No description available",
50
51
  imageUrl: plan.configuration?.imageUrl || "",
@@ -30,6 +30,7 @@ export class SubscriptionTools extends BaseAssistantTools {
30
30
  for (const subscription of status.availableSubscriptions) {
31
31
  agentChips += `<div class="agent-chips"><yp-agent-chip-for-purchase
32
32
  isSubscribed="${true}"
33
+ type="${subscription.Plan?.configuration.type}"
33
34
  agentProductId="${subscription.Plan?.AgentProduct?.id}"
34
35
  subscriptionPlanId="${subscription.Plan?.id}"
35
36
  agentName="${subscription.Plan?.AgentProduct?.name}"
@@ -87,10 +88,37 @@ export class SubscriptionTools extends BaseAssistantTools {
87
88
  console.log(`list_all_agents_available_for_purchase: ${JSON.stringify(status, null, 2)}`);
88
89
  }
89
90
  let agentChips = "";
90
- const sortedPlans = [...status.availablePlans].sort((a, b) => b.price - a.price);
91
+ function planTypePriority(type) {
92
+ switch (type) {
93
+ case "coming_soon":
94
+ return 0;
95
+ case "paid":
96
+ return 1;
97
+ case "free_trial":
98
+ return 2;
99
+ default:
100
+ return 999;
101
+ }
102
+ }
103
+ // 2) Custom sort function
104
+ const sortedPlans = [...status.availablePlans].sort((a, b) => {
105
+ // Compare by type priority first
106
+ const typeComparison = planTypePriority(a.type) - planTypePriority(b.type);
107
+ if (typeComparison !== 0) {
108
+ // If types differ, that decides the order
109
+ return typeComparison;
110
+ }
111
+ // If both are the same type and it's "paid", sort by price descending
112
+ if (a.type === "paid" && b.type === "paid") {
113
+ return b.price - a.price;
114
+ }
115
+ // Otherwise keep them in the same order if they're not "paid"
116
+ return 0;
117
+ });
91
118
  for (const agent of sortedPlans) {
92
119
  agentChips += `<yp-agent-chip-for-purchase
93
120
  subscriptionPlanId="${agent.subscriptionPlanId}"
121
+ type="${agent.type}"
94
122
  agentName="${agent.name}"
95
123
  agentDescription="${agent.description}"
96
124
  agentImageUrl="${agent.imageUrl}"
@@ -122,7 +150,7 @@ export class SubscriptionTools extends BaseAssistantTools {
122
150
  get subscribeToCurrentAgentPlan() {
123
151
  return {
124
152
  name: "subscribe_to_current_agent_plan",
125
- description: "Subscribe to the current agent plan. User must confirm subscription with the agent name before proceeding. The user needs to subscribe to the agent before it can be used.",
153
+ description: "Subscribe to the current agent plan. User must confirm subscription with the agent name before proceeding. The user needs to subscribe to the agent before it can be used so make sure to offer it to the user.",
126
154
  type: "function",
127
155
  parameters: {
128
156
  type: "object",
@@ -182,12 +210,12 @@ export class SubscriptionTools extends BaseAssistantTools {
182
210
  maxRunsPerCycle="${result.plan.configuration.max_runs_per_cycle}"
183
211
  ></yp-agent-chip-for-purchase></div>`;
184
212
  }
185
- this.assistant.emit("update-ai-model-session", "Successfully subscribed to agent plan, now offer to start and show the configuration tool/widget");
213
+ this.assistant.emit("update-ai-model-session", "Successfully subscribed to agent plan, now offer to show the configuration input tool/widget to configure the agent");
186
214
  return {
187
215
  success: true,
188
216
  html,
189
217
  data: {
190
- message: "Successfully subscribed to agent plan, now the user can configure the agent",
218
+ message: "Successfully subscribed to agent plan, now offer to show the configuration input tool/widget to configure the agent",
191
219
  subscription: result.subscription,
192
220
  subscriptionPlan: result.plan,
193
221
  },
@@ -69,7 +69,8 @@ export class NotificationAgentQueueManager extends AgentQueueManager {
69
69
  ${link ? `<p><a href="${link}">${link}</a></p>` : ""}
70
70
  </div>
71
71
  `;
72
- for (let u = 0; u < Math.min(admins.length, 50); u++) {
72
+ const MAX_ADMIN_EMAILS = 25;
73
+ for (let u = 0; u < Math.min(admins.length, MAX_ADMIN_EMAILS); u++) {
73
74
  queue.add("send-one-email", {
74
75
  subject: subject,
75
76
  template: "general_user_notification",
@@ -267,7 +268,7 @@ export class NotificationAgentQueueManager extends AgentQueueManager {
267
268
  console.error(`NotificationAgentQueueManager: Agent run ID ${agentRunId} not found.`);
268
269
  }
269
270
  if (agent) {
270
- // Send websocket notification
271
+ // Send notification
271
272
  await this.sendNotification(agent, agentRun, type, wsClientId, agentRun.status, returnvalue, agentRunId, updatedWorkflow);
272
273
  }
273
274
  else {
@@ -1,63 +1,63 @@
1
1
  import { YpAgentProduct } from "../agentProduct.js";
2
2
  import { YpSubscriptionPlan } from "../subscriptionPlan.js";
3
3
  async function setupAgentProductsConfiguration() {
4
+ const competitionAgentWorkflow = {
5
+ currentStepIndex: 0,
6
+ steps: [
7
+ {
8
+ name: "Competitor Analysis Wide Search",
9
+ shortName: "Wide search",
10
+ description: "Wide search for competitor strategies and market positions.",
11
+ shortDescription: "Wide search for competitor strategies and market positions.",
12
+ agentClassUuid: "a1b2c3d4-e5f6-c7c8-a9c0-c1225354f516",
13
+ type: "agentOps",
14
+ stepBackgroundColor: "#ffdc2f",
15
+ stepTextColor: "#211e1c",
16
+ },
17
+ {
18
+ name: "Competitor Analysis People Review",
19
+ shortName: "Vetting competitors",
20
+ description: "People Review to vet key competitors",
21
+ shortDescription: "People Review to vet key competitors",
22
+ agentClassUuid: "a1b2c3d4-e5f6-c7c8-a9c0-c1225354f516",
23
+ type: "engagmentFromOutputConnector",
24
+ stepBackgroundColor: "#e74c3c",
25
+ stepTextColor: "#ffffff",
26
+ },
27
+ {
28
+ name: "Competitor Analysis Detailed Search",
29
+ shortName: "Detailed search",
30
+ description: "Detailed search for competitor strategies and market positions.",
31
+ shortDescription: "Detailed search for competitor strategies and market positions.",
32
+ agentClassUuid: "c6e99ac4-e5f6-c7c1-a1c0-c1ab53c4ff16",
33
+ type: "agentOps",
34
+ stepBackgroundColor: "#1e90ff",
35
+ stepTextColor: "#ffffff",
36
+ },
37
+ {
38
+ name: "Competitor Analysis Detailed Search People Review",
39
+ shortName: "Key competitors",
40
+ description: "People review of key competitors",
41
+ shortDescription: "People review of key competitors",
42
+ agentClassUuid: "c6e99ac4-e5f6-c7c1-a1c0-c1ab53c4ff16",
43
+ type: "engagmentFromOutputConnector",
44
+ stepBackgroundColor: "#2ecc71",
45
+ stepTextColor: "#ffffff",
46
+ },
47
+ {
48
+ name: "Competitors Report",
49
+ shortName: "Competitor report",
50
+ description: "Report on the state of the market based on the competitors analysis.",
51
+ shortDescription: "Report on the state of the market based on the competitors analysis.",
52
+ agentClassUuid: "1cf3af64-a5f6-a7c1-91c1-51fb13c72f1a",
53
+ type: "agentOps",
54
+ stepBackgroundColor: "#d486da",
55
+ stepTextColor: "#ffffff",
56
+ },
57
+ ],
58
+ };
4
59
  const competitorAgentFreeTrial = await YpAgentProduct.findByPk(1);
5
60
  if (competitorAgentFreeTrial) {
6
- const competitionAgentWorkflow = {
7
- currentStepIndex: 0,
8
- steps: [
9
- {
10
- name: "Competitor Analysis Wide Search",
11
- shortName: "Wide search",
12
- description: "Wide search for competitor strategies and market positions.",
13
- shortDescription: "Wide search for competitor strategies and market positions.",
14
- agentClassUuid: "a1b2c3d4-e5f6-c7c8-a9c0-c1225354f516",
15
- type: "agentOps",
16
- stepBackgroundColor: "#ffdc2f",
17
- stepTextColor: "#211e1c",
18
- },
19
- {
20
- name: "Competitor Analysis People Review",
21
- shortName: "Vetting competitors",
22
- description: "People Review to vet key competitors",
23
- shortDescription: "People Review to vet key competitors",
24
- agentClassUuid: "a1b2c3d4-e5f6-c7c8-a9c0-c1225354f516",
25
- type: "engagmentFromOutputConnector",
26
- stepBackgroundColor: "#e74c3c",
27
- stepTextColor: "#ffffff",
28
- },
29
- {
30
- name: "Competitor Analysis Detailed Search",
31
- shortName: "Detailed search",
32
- description: "Detailed search for competitor strategies and market positions.",
33
- shortDescription: "Detailed search for competitor strategies and market positions.",
34
- agentClassUuid: "c6e99ac4-e5f6-c7c1-a1c0-c1ab53c4ff16",
35
- type: "agentOps",
36
- stepBackgroundColor: "#1e90ff",
37
- stepTextColor: "#ffffff",
38
- },
39
- {
40
- name: "Competitor Analysis Detailed Search People Review",
41
- shortName: "Key competitors",
42
- description: "People review of key competitors",
43
- shortDescription: "People review of key competitors",
44
- agentClassUuid: "c6e99ac4-e5f6-c7c1-a1c0-c1ab53c4ff16",
45
- type: "engagmentFromOutputConnector",
46
- stepBackgroundColor: "#2ecc71",
47
- stepTextColor: "#ffffff",
48
- },
49
- {
50
- name: "Competitors Report",
51
- shortName: "Competitor report",
52
- description: "Report on the state of the market based on the competitors analysis.",
53
- shortDescription: "Report on the state of the market based on the competitors analysis.",
54
- agentClassUuid: "1cf3af64-a5f6-a7c1-91c1-51fb13c72f1a",
55
- type: "agentOps",
56
- stepBackgroundColor: "#d486da",
57
- stepTextColor: "#ffffff",
58
- },
59
- ],
60
- };
61
61
  competitorAgentFreeTrial.set("configuration.workflow", competitionAgentWorkflow);
62
62
  competitorAgentFreeTrial.changed("configuration", true);
63
63
  await competitorAgentFreeTrial.save();
@@ -65,6 +65,12 @@ async function setupAgentProductsConfiguration() {
65
65
  else {
66
66
  console.log("CompetitorAgentFreeTrial not found");
67
67
  }
68
+ const competitorAgentPaid = await YpAgentProduct.findByPk(2);
69
+ if (competitorAgentPaid) {
70
+ competitorAgentPaid.set("configuration.workflow", competitionAgentWorkflow);
71
+ competitorAgentPaid.changed("configuration", true);
72
+ await competitorAgentPaid.save();
73
+ }
68
74
  const fundingAgent = await YpAgentProduct.findByPk(6);
69
75
  if (fundingAgent) {
70
76
  const fundingAgentWorkflow = {
@@ -141,6 +147,28 @@ async function setupAgentProductsConfiguration() {
141
147
  charCounter: true,
142
148
  text: "Business Description",
143
149
  },
150
+ {
151
+ uniqueId: "investorGeographicFocus",
152
+ type: "textFieldLong",
153
+ description: "Geographic focus of the investors",
154
+ value: "",
155
+ maxLength: 250,
156
+ required: false,
157
+ rows: 1,
158
+ charCounter: true,
159
+ text: "Investor Geographic Focus",
160
+ },
161
+ {
162
+ uniqueId: "investorIndustryFocus",
163
+ type: "textFieldLong",
164
+ description: "Industry focus of the investors",
165
+ value: "",
166
+ maxLength: 250,
167
+ required: false,
168
+ rows: 1,
169
+ charCounter: true,
170
+ text: "Investor Industry Focus",
171
+ }
144
172
  ]);
145
173
  fundingSubscriptionPlan.changed("configuration", true);
146
174
  await fundingSubscriptionPlan.save();
@@ -148,5 +176,20 @@ async function setupAgentProductsConfiguration() {
148
176
  else {
149
177
  console.log("FundingSubscriptionPlan not found");
150
178
  }
179
+ // Update subscription plans 2-5 to coming_soon
180
+ for (let planId = 2; planId <= 5; planId++) {
181
+ const subscriptionPlan = await YpSubscriptionPlan.findByPk(planId);
182
+ if (subscriptionPlan) {
183
+ subscriptionPlan.set("configuration.type", "coming_soon");
184
+ if (planId == 2) {
185
+ subscriptionPlan.set("configuration.type", "paid");
186
+ }
187
+ subscriptionPlan.changed("configuration", true);
188
+ await subscriptionPlan.save();
189
+ }
190
+ else {
191
+ console.log(`SubscriptionPlan ${planId} not found`);
192
+ }
193
+ }
151
194
  }
152
195
  setupAgentProductsConfiguration();
package/app.js CHANGED
@@ -298,7 +298,7 @@ export class YourPrioritiesApi {
298
298
  }
299
299
  addInviteAsAnonMiddleWare() {
300
300
  this.app.use(async (req, res, next) => {
301
- if (!req.user && req.query.anonInvite && req.query.token) {
301
+ if (req.query.anonInvite && req.query.token) {
302
302
  const token = req.query.token;
303
303
  try {
304
304
  //TODO: Fix this "as any" in all places
@@ -317,9 +317,15 @@ export class YourPrioritiesApi {
317
317
  });
318
318
  if (invite) {
319
319
  const anonEmail = req.sessionID + "_v3anonymous@citizens.is";
320
- let user = await models.User.findOne({
321
- where: { email: anonEmail },
322
- });
320
+ let user;
321
+ if (req.user) {
322
+ user = req.user;
323
+ }
324
+ else {
325
+ user = await models.User.findOne({
326
+ where: { email: anonEmail },
327
+ });
328
+ }
323
329
  if (!user) {
324
330
  user = await models.User.create({
325
331
  email: anonEmail,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yrpri/api",
3
- "version": "9.0.80",
3
+ "version": "9.0.81",
4
4
  "license": "MIT",
5
5
  "author": "Robert Bjarnason & Citizens Foundation",
6
6
  "repository": {