@chaaskit/server 0.1.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/api/admin.js +438 -0
- package/dist/api/admin.js.map +1 -0
- package/dist/api/agents.js +21 -0
- package/dist/api/agents.js.map +1 -0
- package/dist/api/api-keys.js +122 -0
- package/dist/api/api-keys.js.map +1 -0
- package/dist/api/auth.js +399 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/chat.js +900 -0
- package/dist/api/chat.js.map +1 -0
- package/dist/api/config.js +91 -0
- package/dist/api/config.js.map +1 -0
- package/dist/api/documents.js +237 -0
- package/dist/api/documents.js.map +1 -0
- package/dist/api/export.js +107 -0
- package/dist/api/export.js.map +1 -0
- package/dist/api/health.js +25 -0
- package/dist/api/health.js.map +1 -0
- package/dist/api/mcp-server.js +84 -0
- package/dist/api/mcp-server.js.map +1 -0
- package/dist/api/mcp.js +400 -0
- package/dist/api/mcp.js.map +1 -0
- package/dist/api/mentions.js +94 -0
- package/dist/api/mentions.js.map +1 -0
- package/dist/api/oauth.js +366 -0
- package/dist/api/oauth.js.map +1 -0
- package/dist/api/payments.js +473 -0
- package/dist/api/payments.js.map +1 -0
- package/dist/api/projects.js +301 -0
- package/dist/api/projects.js.map +1 -0
- package/dist/api/scheduled-prompts.js +617 -0
- package/dist/api/scheduled-prompts.js.map +1 -0
- package/dist/api/search.js +85 -0
- package/dist/api/search.js.map +1 -0
- package/dist/api/share.js +188 -0
- package/dist/api/share.js.map +1 -0
- package/dist/api/slack.js +468 -0
- package/dist/api/slack.js.map +1 -0
- package/dist/api/teams.js +693 -0
- package/dist/api/teams.js.map +1 -0
- package/dist/api/templates.js +134 -0
- package/dist/api/templates.js.map +1 -0
- package/dist/api/threads.js +323 -0
- package/dist/api/threads.js.map +1 -0
- package/dist/api/upload.js +57 -0
- package/dist/api/upload.js.map +1 -0
- package/dist/api/user.js +111 -0
- package/dist/api/user.js.map +1 -0
- package/dist/api/v1/openai.js +245 -0
- package/dist/api/v1/openai.js.map +1 -0
- package/dist/app.js +168 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/cli.js +57 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/commands/db-sync.js +108 -0
- package/dist/commands/db-sync.js.map +1 -0
- package/dist/config/loader.js +374 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/documents/extractors.js +136 -0
- package/dist/documents/extractors.js.map +1 -0
- package/dist/extensions/glob.js +53 -0
- package/dist/extensions/glob.js.map +1 -0
- package/dist/extensions/loader.js +72 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/loaders/index.js +75 -0
- package/dist/loaders/index.js.map +1 -0
- package/dist/mcp/client.js +551 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/server.js +335 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/middleware/apiKeyAuth.js +136 -0
- package/dist/middleware/apiKeyAuth.js.map +1 -0
- package/dist/middleware/auth.js +192 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/errorHandler.js +41 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/mcpServerAuth.js +164 -0
- package/dist/middleware/mcpServerAuth.js.map +1 -0
- package/dist/middleware/requestLogger.js +9 -0
- package/dist/middleware/requestLogger.js.map +1 -0
- package/dist/middleware/team.js +132 -0
- package/dist/middleware/team.js.map +1 -0
- package/dist/oauth/server.js +410 -0
- package/dist/oauth/server.js.map +1 -0
- package/dist/queue/cli.js +93 -0
- package/dist/queue/cli.js.map +1 -0
- package/dist/queue/handlers/index.js +91 -0
- package/dist/queue/handlers/index.js.map +1 -0
- package/dist/queue/handlers/scheduled-prompt.js +270 -0
- package/dist/queue/handlers/scheduled-prompt.js.map +1 -0
- package/dist/queue/index.js +91 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/providers/memory.js +296 -0
- package/dist/queue/providers/memory.js.map +1 -0
- package/dist/queue/providers/sqs.js +275 -0
- package/dist/queue/providers/sqs.js.map +1 -0
- package/dist/queue/scheduler.js +355 -0
- package/dist/queue/scheduler.js.map +1 -0
- package/dist/queue/types.js +5 -0
- package/dist/queue/types.js.map +1 -0
- package/dist/queue/worker.js +230 -0
- package/dist/queue/worker.js.map +1 -0
- package/dist/registry/index.js +40 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/server.js +207 -0
- package/dist/server.js.map +1 -0
- package/dist/services/agent.js +530 -0
- package/dist/services/agent.js.map +1 -0
- package/dist/services/agents.js +194 -0
- package/dist/services/agents.js.map +1 -0
- package/dist/services/documents.js +507 -0
- package/dist/services/documents.js.map +1 -0
- package/dist/services/email/index.js +91 -0
- package/dist/services/email/index.js.map +1 -0
- package/dist/services/email/providers/ses.js +97 -0
- package/dist/services/email/providers/ses.js.map +1 -0
- package/dist/services/email/templates.js +194 -0
- package/dist/services/email/templates.js.map +1 -0
- package/dist/services/email/types.js +5 -0
- package/dist/services/email/types.js.map +1 -0
- package/dist/services/encryption.js +69 -0
- package/dist/services/encryption.js.map +1 -0
- package/dist/services/oauth-discovery.js +226 -0
- package/dist/services/oauth-discovery.js.map +1 -0
- package/dist/services/pendingConfirmation.js +105 -0
- package/dist/services/pendingConfirmation.js.map +1 -0
- package/dist/services/scheduledPrompts.js +70 -0
- package/dist/services/scheduledPrompts.js.map +1 -0
- package/dist/services/slack/client.js +174 -0
- package/dist/services/slack/client.js.map +1 -0
- package/dist/services/slack/events.js +189 -0
- package/dist/services/slack/events.js.map +1 -0
- package/dist/services/slack/index.js +6 -0
- package/dist/services/slack/index.js.map +1 -0
- package/dist/services/slack/notifications.js +124 -0
- package/dist/services/slack/notifications.js.map +1 -0
- package/dist/services/slack/signature.js +74 -0
- package/dist/services/slack/signature.js.map +1 -0
- package/dist/services/slack/thread-context.js +191 -0
- package/dist/services/slack/thread-context.js.map +1 -0
- package/dist/services/toolConfirmation.js +55 -0
- package/dist/services/toolConfirmation.js.map +1 -0
- package/dist/services/usage.js +241 -0
- package/dist/services/usage.js.map +1 -0
- package/dist/ssr/build.js +90 -0
- package/dist/ssr/build.js.map +1 -0
- package/dist/ssr/components/SSRMessageList.js +120 -0
- package/dist/ssr/components/SSRMessageList.js.map +1 -0
- package/dist/ssr/entry.client.js +8 -0
- package/dist/ssr/entry.client.js.map +1 -0
- package/dist/ssr/entry.server.js +71 -0
- package/dist/ssr/entry.server.js.map +1 -0
- package/dist/ssr/handler.js +51 -0
- package/dist/ssr/handler.js.map +1 -0
- package/dist/ssr/root.js +184 -0
- package/dist/ssr/root.js.map +1 -0
- package/dist/ssr/routes/login.js +140 -0
- package/dist/ssr/routes/login.js.map +1 -0
- package/dist/ssr/routes/pricing.js +195 -0
- package/dist/ssr/routes/pricing.js.map +1 -0
- package/dist/ssr/routes/privacy.js +39 -0
- package/dist/ssr/routes/privacy.js.map +1 -0
- package/dist/ssr/routes/register.js +148 -0
- package/dist/ssr/routes/register.js.map +1 -0
- package/dist/ssr/routes/shared.$shareId.js +153 -0
- package/dist/ssr/routes/shared.$shareId.js.map +1 -0
- package/dist/ssr/routes/terms.js +39 -0
- package/dist/ssr/routes/terms.js.map +1 -0
- package/dist/storage/index.js +43 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/providers/database.js +38 -0
- package/dist/storage/providers/database.js.map +1 -0
- package/dist/storage/providers/filesystem.js +51 -0
- package/dist/storage/providers/filesystem.js.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/tools/documents.js +336 -0
- package/dist/tools/documents.js.map +1 -0
- package/dist/tools/get-plan-usage.js +82 -0
- package/dist/tools/get-plan-usage.js.map +1 -0
- package/dist/tools/index.js +106 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/web-scrape.js +145 -0
- package/dist/tools/web-scrape.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduled Prompts (Automations) API
|
|
3
|
+
*
|
|
4
|
+
* CRUD endpoints for scheduled prompts that run on a schedule,
|
|
5
|
+
* create threads with results, and send notifications.
|
|
6
|
+
*/
|
|
7
|
+
import { Router } from 'express';
|
|
8
|
+
import { db } from '@chaaskit/db';
|
|
9
|
+
import { HTTP_STATUS } from '@chaaskit/shared';
|
|
10
|
+
import { requireAuth } from '../middleware/auth.js';
|
|
11
|
+
import { AppError } from '../middleware/errorHandler.js';
|
|
12
|
+
import { getConfig } from '../config/loader.js';
|
|
13
|
+
import { getAgentById, getDefaultAgent } from '../services/agents.js';
|
|
14
|
+
import { getScheduler, getQueueProvider } from '../queue/index.js';
|
|
15
|
+
import { CronExpressionParser } from 'cron-parser';
|
|
16
|
+
export const scheduledPromptsRouter = Router();
|
|
17
|
+
// All routes require authentication
|
|
18
|
+
scheduledPromptsRouter.use(requireAuth);
|
|
19
|
+
/**
|
|
20
|
+
* Helper to check if scheduled prompts feature is enabled
|
|
21
|
+
*/
|
|
22
|
+
function requireFeatureEnabled() {
|
|
23
|
+
const config = getConfig();
|
|
24
|
+
if (!config.scheduledPrompts?.enabled) {
|
|
25
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Scheduled prompts feature is disabled');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the user's plan limits for scheduled prompts
|
|
30
|
+
*/
|
|
31
|
+
function getPlanLimits(plan) {
|
|
32
|
+
const config = getConfig().scheduledPrompts;
|
|
33
|
+
if (!config) {
|
|
34
|
+
return { maxUserPrompts: 0, maxTeamPrompts: 0 };
|
|
35
|
+
}
|
|
36
|
+
const planLimits = config.planLimits?.find((p) => p.plan === plan);
|
|
37
|
+
return {
|
|
38
|
+
maxUserPrompts: planLimits?.maxUserPrompts ?? config.defaultMaxUserPrompts ?? 0,
|
|
39
|
+
maxTeamPrompts: planLimits?.maxTeamPrompts ?? config.defaultMaxTeamPrompts ?? 0,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Calculate next run time for a schedule
|
|
44
|
+
*/
|
|
45
|
+
function calculateNextRun(schedule, timezone) {
|
|
46
|
+
// Try interval syntax first
|
|
47
|
+
const intervalMatch = schedule.match(/^every\s+(\d+)\s+(second|minute|hour|day|week)s?$/i);
|
|
48
|
+
if (intervalMatch) {
|
|
49
|
+
const value = parseInt(intervalMatch[1], 10);
|
|
50
|
+
const unit = intervalMatch[2].toLowerCase();
|
|
51
|
+
const multipliers = {
|
|
52
|
+
second: 1000,
|
|
53
|
+
minute: 60 * 1000,
|
|
54
|
+
hour: 60 * 60 * 1000,
|
|
55
|
+
day: 24 * 60 * 60 * 1000,
|
|
56
|
+
week: 7 * 24 * 60 * 60 * 1000,
|
|
57
|
+
};
|
|
58
|
+
return new Date(Date.now() + value * (multipliers[unit] || 0));
|
|
59
|
+
}
|
|
60
|
+
// Parse as cron expression
|
|
61
|
+
try {
|
|
62
|
+
const interval = CronExpressionParser.parse(schedule, {
|
|
63
|
+
currentDate: new Date(),
|
|
64
|
+
tz: timezone,
|
|
65
|
+
});
|
|
66
|
+
return interval.next().toDate();
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Convert database record to summary response
|
|
74
|
+
*/
|
|
75
|
+
function toSummary(prompt) {
|
|
76
|
+
const agent = prompt.agentId ? getAgentById(prompt.agentId) : getDefaultAgent();
|
|
77
|
+
const agentName = agent?.name ?? 'Unknown';
|
|
78
|
+
const nextRunAt = prompt.enabled
|
|
79
|
+
? calculateNextRun(prompt.schedule, prompt.timezone)
|
|
80
|
+
: null;
|
|
81
|
+
return {
|
|
82
|
+
id: prompt.id,
|
|
83
|
+
name: prompt.name,
|
|
84
|
+
schedule: prompt.schedule,
|
|
85
|
+
timezone: prompt.timezone,
|
|
86
|
+
enabled: prompt.enabled,
|
|
87
|
+
agentId: prompt.agentId,
|
|
88
|
+
agentName,
|
|
89
|
+
lastRunAt: prompt.lastRunAt?.toISOString() ?? null,
|
|
90
|
+
lastRunStatus: prompt.lastRunStatus,
|
|
91
|
+
nextRunAt: nextRunAt?.toISOString() ?? null,
|
|
92
|
+
runCount: prompt.runCount,
|
|
93
|
+
userId: prompt.userId,
|
|
94
|
+
teamId: prompt.teamId,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Convert database record to detail response
|
|
99
|
+
*/
|
|
100
|
+
function toDetail(prompt) {
|
|
101
|
+
const summary = toSummary(prompt);
|
|
102
|
+
let emailRecipients = [];
|
|
103
|
+
try {
|
|
104
|
+
if (prompt.emailRecipients) {
|
|
105
|
+
emailRecipients = JSON.parse(prompt.emailRecipients);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Invalid JSON, return empty array
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
...summary,
|
|
113
|
+
prompt: prompt.prompt,
|
|
114
|
+
notifySlack: prompt.notifySlack,
|
|
115
|
+
notifyEmail: prompt.notifyEmail,
|
|
116
|
+
emailRecipients,
|
|
117
|
+
threadId: prompt.threadId,
|
|
118
|
+
createdAt: prompt.createdAt.toISOString(),
|
|
119
|
+
updatedAt: prompt.updatedAt.toISOString(),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Sync a scheduled prompt to the RecurringJob table
|
|
124
|
+
*/
|
|
125
|
+
async function syncToRecurringJob(promptId, enabled) {
|
|
126
|
+
const scheduler = getScheduler();
|
|
127
|
+
if (!scheduler) {
|
|
128
|
+
return; // Scheduler not running
|
|
129
|
+
}
|
|
130
|
+
const recurringJobName = `scheduled-prompt:${promptId}`;
|
|
131
|
+
if (!enabled) {
|
|
132
|
+
// Disable the recurring job
|
|
133
|
+
await scheduler.disableRecurring(recurringJobName);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Get the prompt details
|
|
137
|
+
const prompt = await db.scheduledPrompt.findUnique({
|
|
138
|
+
where: { id: promptId },
|
|
139
|
+
});
|
|
140
|
+
if (!prompt)
|
|
141
|
+
return;
|
|
142
|
+
// Register/update the recurring job
|
|
143
|
+
await scheduler.registerRecurring({
|
|
144
|
+
name: recurringJobName,
|
|
145
|
+
type: 'scheduled-prompt:execute',
|
|
146
|
+
payload: { scheduledPromptId: promptId },
|
|
147
|
+
schedule: prompt.schedule,
|
|
148
|
+
timezone: prompt.timezone,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Remove a scheduled prompt's recurring job
|
|
153
|
+
*/
|
|
154
|
+
async function removeRecurringJob(promptId) {
|
|
155
|
+
const recurringJobName = `scheduled-prompt:${promptId}`;
|
|
156
|
+
await db.recurringJob.deleteMany({
|
|
157
|
+
where: { name: recurringJobName },
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* GET /api/scheduled-prompts
|
|
162
|
+
* List scheduled prompts for the current user and their teams
|
|
163
|
+
*
|
|
164
|
+
* Query params:
|
|
165
|
+
* - teamId: Filter to specific team
|
|
166
|
+
* - personal: Set to "true" to filter to personal prompts only
|
|
167
|
+
*/
|
|
168
|
+
scheduledPromptsRouter.get('/', async (req, res, next) => {
|
|
169
|
+
try {
|
|
170
|
+
requireFeatureEnabled();
|
|
171
|
+
const userId = req.user.id;
|
|
172
|
+
const userPlan = req.user.plan;
|
|
173
|
+
const { teamId, personal } = req.query;
|
|
174
|
+
// Build where clause
|
|
175
|
+
const whereClause = {};
|
|
176
|
+
// Variables for limits response
|
|
177
|
+
let currentCount = 0;
|
|
178
|
+
let maxCount = 0;
|
|
179
|
+
let limitContext = 'all';
|
|
180
|
+
if (teamId && typeof teamId === 'string') {
|
|
181
|
+
// Filter to specific team - verify membership
|
|
182
|
+
const membership = await db.teamMember.findUnique({
|
|
183
|
+
where: {
|
|
184
|
+
teamId_userId: {
|
|
185
|
+
teamId,
|
|
186
|
+
userId,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
include: { team: true },
|
|
190
|
+
});
|
|
191
|
+
if (!membership) {
|
|
192
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Not a member of this team');
|
|
193
|
+
}
|
|
194
|
+
whereClause.teamId = teamId;
|
|
195
|
+
limitContext = 'team';
|
|
196
|
+
// Get limits for this team
|
|
197
|
+
const teamPlan = membership.team.plan;
|
|
198
|
+
const limits = getPlanLimits(teamPlan);
|
|
199
|
+
maxCount = limits.maxTeamPrompts;
|
|
200
|
+
currentCount = await db.scheduledPrompt.count({
|
|
201
|
+
where: { teamId },
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
else if (personal === 'true') {
|
|
205
|
+
// Filter to personal prompts only
|
|
206
|
+
whereClause.userId = userId;
|
|
207
|
+
whereClause.teamId = null;
|
|
208
|
+
limitContext = 'personal';
|
|
209
|
+
// Get limits for user
|
|
210
|
+
const limits = getPlanLimits(userPlan);
|
|
211
|
+
maxCount = limits.maxUserPrompts;
|
|
212
|
+
currentCount = await db.scheduledPrompt.count({
|
|
213
|
+
where: { userId, teamId: null },
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// Get user's prompts + team prompts they can access
|
|
218
|
+
const teamMemberships = await db.teamMember.findMany({
|
|
219
|
+
where: { userId },
|
|
220
|
+
select: { teamId: true },
|
|
221
|
+
});
|
|
222
|
+
const teamIds = teamMemberships.map((m) => m.teamId);
|
|
223
|
+
whereClause.OR = [
|
|
224
|
+
{ userId },
|
|
225
|
+
...(teamIds.length > 0 ? teamIds.map((id) => ({ teamId: id })) : []),
|
|
226
|
+
];
|
|
227
|
+
}
|
|
228
|
+
const prompts = await db.scheduledPrompt.findMany({
|
|
229
|
+
where: whereClause,
|
|
230
|
+
orderBy: { createdAt: 'desc' },
|
|
231
|
+
});
|
|
232
|
+
const summaries = prompts.map(toSummary);
|
|
233
|
+
res.json({
|
|
234
|
+
prompts: summaries,
|
|
235
|
+
limits: {
|
|
236
|
+
context: limitContext,
|
|
237
|
+
current: currentCount,
|
|
238
|
+
max: maxCount,
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
next(error);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
/**
|
|
247
|
+
* GET /api/scheduled-prompts/:id
|
|
248
|
+
* Get a single scheduled prompt
|
|
249
|
+
*/
|
|
250
|
+
scheduledPromptsRouter.get('/:id', async (req, res, next) => {
|
|
251
|
+
try {
|
|
252
|
+
requireFeatureEnabled();
|
|
253
|
+
const userId = req.user.id;
|
|
254
|
+
const { id } = req.params;
|
|
255
|
+
const prompt = await db.scheduledPrompt.findUnique({
|
|
256
|
+
where: { id },
|
|
257
|
+
});
|
|
258
|
+
if (!prompt) {
|
|
259
|
+
throw new AppError(HTTP_STATUS.NOT_FOUND, 'Scheduled prompt not found');
|
|
260
|
+
}
|
|
261
|
+
// Check access
|
|
262
|
+
if (prompt.userId && prompt.userId !== userId) {
|
|
263
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
264
|
+
}
|
|
265
|
+
if (prompt.teamId) {
|
|
266
|
+
const membership = await db.teamMember.findUnique({
|
|
267
|
+
where: {
|
|
268
|
+
teamId_userId: {
|
|
269
|
+
teamId: prompt.teamId,
|
|
270
|
+
userId,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
if (!membership) {
|
|
275
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
res.json({ prompt: toDetail(prompt) });
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
next(error);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
/**
|
|
285
|
+
* POST /api/scheduled-prompts
|
|
286
|
+
* Create a new scheduled prompt
|
|
287
|
+
*/
|
|
288
|
+
scheduledPromptsRouter.post('/', async (req, res, next) => {
|
|
289
|
+
try {
|
|
290
|
+
requireFeatureEnabled();
|
|
291
|
+
const userId = req.user.id;
|
|
292
|
+
const userPlan = req.user.plan;
|
|
293
|
+
const body = req.body;
|
|
294
|
+
// Validate required fields
|
|
295
|
+
if (!body.name?.trim()) {
|
|
296
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Name is required');
|
|
297
|
+
}
|
|
298
|
+
if (!body.prompt?.trim()) {
|
|
299
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Prompt is required');
|
|
300
|
+
}
|
|
301
|
+
if (!body.schedule?.trim()) {
|
|
302
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Schedule is required');
|
|
303
|
+
}
|
|
304
|
+
// Validate schedule format
|
|
305
|
+
const timezone = body.timezone || 'UTC';
|
|
306
|
+
const nextRun = calculateNextRun(body.schedule, timezone);
|
|
307
|
+
if (!nextRun) {
|
|
308
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Invalid schedule format');
|
|
309
|
+
}
|
|
310
|
+
// Validate agent if provided
|
|
311
|
+
if (body.agentId) {
|
|
312
|
+
const agent = getAgentById(body.agentId);
|
|
313
|
+
if (!agent) {
|
|
314
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Invalid agent');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// Determine ownership and check limits
|
|
318
|
+
let ownerUserId = null;
|
|
319
|
+
let ownerTeamId = null;
|
|
320
|
+
if (body.teamId) {
|
|
321
|
+
// Creating for team - check membership and admin role
|
|
322
|
+
const membership = await db.teamMember.findUnique({
|
|
323
|
+
where: {
|
|
324
|
+
teamId_userId: {
|
|
325
|
+
teamId: body.teamId,
|
|
326
|
+
userId,
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
include: { team: true },
|
|
330
|
+
});
|
|
331
|
+
if (!membership) {
|
|
332
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Not a member of this team');
|
|
333
|
+
}
|
|
334
|
+
if (membership.role !== 'owner' && membership.role !== 'admin') {
|
|
335
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Only team owners and admins can create scheduled prompts');
|
|
336
|
+
}
|
|
337
|
+
// Check team limit
|
|
338
|
+
const teamPlan = membership.team.plan;
|
|
339
|
+
const limits = getPlanLimits(teamPlan);
|
|
340
|
+
const currentCount = await db.scheduledPrompt.count({
|
|
341
|
+
where: { teamId: body.teamId },
|
|
342
|
+
});
|
|
343
|
+
if (currentCount >= limits.maxTeamPrompts) {
|
|
344
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, `Team plan limit reached (${limits.maxTeamPrompts} scheduled prompts)`);
|
|
345
|
+
}
|
|
346
|
+
ownerTeamId = body.teamId;
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
// Creating for user
|
|
350
|
+
const limits = getPlanLimits(userPlan);
|
|
351
|
+
const currentCount = await db.scheduledPrompt.count({
|
|
352
|
+
where: { userId },
|
|
353
|
+
});
|
|
354
|
+
if (currentCount >= limits.maxUserPrompts) {
|
|
355
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, `Plan limit reached (${limits.maxUserPrompts} scheduled prompts)`);
|
|
356
|
+
}
|
|
357
|
+
ownerUserId = userId;
|
|
358
|
+
}
|
|
359
|
+
// Create the scheduled prompt
|
|
360
|
+
const prompt = await db.scheduledPrompt.create({
|
|
361
|
+
data: {
|
|
362
|
+
name: body.name.trim(),
|
|
363
|
+
prompt: body.prompt.trim(),
|
|
364
|
+
agentId: body.agentId || null,
|
|
365
|
+
schedule: body.schedule.trim(),
|
|
366
|
+
timezone,
|
|
367
|
+
enabled: true,
|
|
368
|
+
notifySlack: body.notifySlack ?? true,
|
|
369
|
+
notifyEmail: body.notifyEmail ?? false,
|
|
370
|
+
emailRecipients: body.emailRecipients ? JSON.stringify(body.emailRecipients) : null,
|
|
371
|
+
userId: ownerUserId,
|
|
372
|
+
teamId: ownerTeamId,
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
// Sync to recurring job
|
|
376
|
+
await syncToRecurringJob(prompt.id, true);
|
|
377
|
+
res.status(HTTP_STATUS.CREATED).json({ prompt: toDetail(prompt) });
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
next(error);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
/**
|
|
384
|
+
* PUT /api/scheduled-prompts/:id
|
|
385
|
+
* Update an existing scheduled prompt
|
|
386
|
+
*/
|
|
387
|
+
scheduledPromptsRouter.put('/:id', async (req, res, next) => {
|
|
388
|
+
try {
|
|
389
|
+
requireFeatureEnabled();
|
|
390
|
+
const userId = req.user.id;
|
|
391
|
+
const { id } = req.params;
|
|
392
|
+
const body = req.body;
|
|
393
|
+
// Get existing prompt
|
|
394
|
+
const existing = await db.scheduledPrompt.findUnique({
|
|
395
|
+
where: { id },
|
|
396
|
+
});
|
|
397
|
+
if (!existing) {
|
|
398
|
+
throw new AppError(HTTP_STATUS.NOT_FOUND, 'Scheduled prompt not found');
|
|
399
|
+
}
|
|
400
|
+
// Check access - only owner or team admin can update
|
|
401
|
+
if (existing.userId && existing.userId !== userId) {
|
|
402
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
403
|
+
}
|
|
404
|
+
if (existing.teamId) {
|
|
405
|
+
const membership = await db.teamMember.findUnique({
|
|
406
|
+
where: {
|
|
407
|
+
teamId_userId: {
|
|
408
|
+
teamId: existing.teamId,
|
|
409
|
+
userId,
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
if (!membership) {
|
|
414
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
415
|
+
}
|
|
416
|
+
if (membership.role !== 'owner' && membership.role !== 'admin') {
|
|
417
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Only team owners and admins can update scheduled prompts');
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// Validate schedule if provided
|
|
421
|
+
if (body.schedule) {
|
|
422
|
+
const timezone = body.timezone || existing.timezone;
|
|
423
|
+
const nextRun = calculateNextRun(body.schedule, timezone);
|
|
424
|
+
if (!nextRun) {
|
|
425
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Invalid schedule format');
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
// Validate agent if provided
|
|
429
|
+
if (body.agentId !== undefined && body.agentId !== null) {
|
|
430
|
+
const agent = getAgentById(body.agentId);
|
|
431
|
+
if (!agent) {
|
|
432
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Invalid agent');
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// Update the prompt
|
|
436
|
+
const prompt = await db.scheduledPrompt.update({
|
|
437
|
+
where: { id },
|
|
438
|
+
data: {
|
|
439
|
+
...(body.name !== undefined && { name: body.name.trim() }),
|
|
440
|
+
...(body.prompt !== undefined && { prompt: body.prompt.trim() }),
|
|
441
|
+
...(body.agentId !== undefined && { agentId: body.agentId }),
|
|
442
|
+
...(body.schedule !== undefined && { schedule: body.schedule.trim() }),
|
|
443
|
+
...(body.timezone !== undefined && { timezone: body.timezone }),
|
|
444
|
+
...(body.enabled !== undefined && { enabled: body.enabled }),
|
|
445
|
+
...(body.notifySlack !== undefined && { notifySlack: body.notifySlack }),
|
|
446
|
+
...(body.notifyEmail !== undefined && { notifyEmail: body.notifyEmail }),
|
|
447
|
+
...(body.emailRecipients !== undefined && {
|
|
448
|
+
emailRecipients: JSON.stringify(body.emailRecipients || []),
|
|
449
|
+
}),
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
// Sync to recurring job
|
|
453
|
+
const enabled = body.enabled !== undefined ? body.enabled : existing.enabled;
|
|
454
|
+
await syncToRecurringJob(prompt.id, enabled);
|
|
455
|
+
res.json({ prompt: toDetail(prompt) });
|
|
456
|
+
}
|
|
457
|
+
catch (error) {
|
|
458
|
+
next(error);
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
/**
|
|
462
|
+
* DELETE /api/scheduled-prompts/:id
|
|
463
|
+
* Delete a scheduled prompt
|
|
464
|
+
*/
|
|
465
|
+
scheduledPromptsRouter.delete('/:id', async (req, res, next) => {
|
|
466
|
+
try {
|
|
467
|
+
requireFeatureEnabled();
|
|
468
|
+
const userId = req.user.id;
|
|
469
|
+
const { id } = req.params;
|
|
470
|
+
// Get existing prompt
|
|
471
|
+
const existing = await db.scheduledPrompt.findUnique({
|
|
472
|
+
where: { id },
|
|
473
|
+
});
|
|
474
|
+
if (!existing) {
|
|
475
|
+
throw new AppError(HTTP_STATUS.NOT_FOUND, 'Scheduled prompt not found');
|
|
476
|
+
}
|
|
477
|
+
// Check access
|
|
478
|
+
if (existing.userId && existing.userId !== userId) {
|
|
479
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
480
|
+
}
|
|
481
|
+
if (existing.teamId) {
|
|
482
|
+
const membership = await db.teamMember.findUnique({
|
|
483
|
+
where: {
|
|
484
|
+
teamId_userId: {
|
|
485
|
+
teamId: existing.teamId,
|
|
486
|
+
userId,
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
if (!membership) {
|
|
491
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
492
|
+
}
|
|
493
|
+
if (membership.role !== 'owner' && membership.role !== 'admin') {
|
|
494
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Only team owners and admins can delete scheduled prompts');
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
// Remove recurring job
|
|
498
|
+
await removeRecurringJob(id);
|
|
499
|
+
// Delete the prompt
|
|
500
|
+
await db.scheduledPrompt.delete({
|
|
501
|
+
where: { id },
|
|
502
|
+
});
|
|
503
|
+
res.status(HTTP_STATUS.NO_CONTENT).send();
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
next(error);
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
/**
|
|
510
|
+
* POST /api/scheduled-prompts/:id/run
|
|
511
|
+
* Manually trigger a scheduled prompt
|
|
512
|
+
*/
|
|
513
|
+
scheduledPromptsRouter.post('/:id/run', async (req, res, next) => {
|
|
514
|
+
try {
|
|
515
|
+
requireFeatureEnabled();
|
|
516
|
+
const userId = req.user.id;
|
|
517
|
+
const { id } = req.params;
|
|
518
|
+
// Get the prompt
|
|
519
|
+
const prompt = await db.scheduledPrompt.findUnique({
|
|
520
|
+
where: { id },
|
|
521
|
+
});
|
|
522
|
+
if (!prompt) {
|
|
523
|
+
throw new AppError(HTTP_STATUS.NOT_FOUND, 'Scheduled prompt not found');
|
|
524
|
+
}
|
|
525
|
+
// Check access
|
|
526
|
+
if (prompt.userId && prompt.userId !== userId) {
|
|
527
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
528
|
+
}
|
|
529
|
+
if (prompt.teamId) {
|
|
530
|
+
const membership = await db.teamMember.findUnique({
|
|
531
|
+
where: {
|
|
532
|
+
teamId_userId: {
|
|
533
|
+
teamId: prompt.teamId,
|
|
534
|
+
userId,
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
});
|
|
538
|
+
if (!membership) {
|
|
539
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
// Enqueue the job immediately
|
|
543
|
+
const queue = getQueueProvider();
|
|
544
|
+
const job = await queue.enqueue('scheduled-prompt:execute', { scheduledPromptId: id });
|
|
545
|
+
res.json({ message: 'Run triggered', jobId: job.id });
|
|
546
|
+
}
|
|
547
|
+
catch (error) {
|
|
548
|
+
next(error);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
/**
|
|
552
|
+
* GET /api/scheduled-prompts/:id/history
|
|
553
|
+
* Get run history for a scheduled prompt (via thread messages)
|
|
554
|
+
*/
|
|
555
|
+
scheduledPromptsRouter.get('/:id/history', async (req, res, next) => {
|
|
556
|
+
try {
|
|
557
|
+
requireFeatureEnabled();
|
|
558
|
+
const userId = req.user.id;
|
|
559
|
+
const { id } = req.params;
|
|
560
|
+
const limit = parseInt(req.query.limit) || 20;
|
|
561
|
+
// Get the prompt
|
|
562
|
+
const prompt = await db.scheduledPrompt.findUnique({
|
|
563
|
+
where: { id },
|
|
564
|
+
include: {
|
|
565
|
+
thread: {
|
|
566
|
+
include: {
|
|
567
|
+
messages: {
|
|
568
|
+
where: { role: 'user' },
|
|
569
|
+
orderBy: { createdAt: 'desc' },
|
|
570
|
+
take: limit,
|
|
571
|
+
select: {
|
|
572
|
+
id: true,
|
|
573
|
+
createdAt: true,
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
},
|
|
577
|
+
},
|
|
578
|
+
},
|
|
579
|
+
});
|
|
580
|
+
if (!prompt) {
|
|
581
|
+
throw new AppError(HTTP_STATUS.NOT_FOUND, 'Scheduled prompt not found');
|
|
582
|
+
}
|
|
583
|
+
// Check access
|
|
584
|
+
if (prompt.userId && prompt.userId !== userId) {
|
|
585
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
586
|
+
}
|
|
587
|
+
if (prompt.teamId) {
|
|
588
|
+
const membership = await db.teamMember.findUnique({
|
|
589
|
+
where: {
|
|
590
|
+
teamId_userId: {
|
|
591
|
+
teamId: prompt.teamId,
|
|
592
|
+
userId,
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
});
|
|
596
|
+
if (!membership) {
|
|
597
|
+
throw new AppError(HTTP_STATUS.FORBIDDEN, 'Access denied');
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
// Build history from thread messages
|
|
601
|
+
const history = prompt.thread?.messages.map((msg) => ({
|
|
602
|
+
id: msg.id,
|
|
603
|
+
runAt: msg.createdAt.toISOString(),
|
|
604
|
+
})) ?? [];
|
|
605
|
+
res.json({
|
|
606
|
+
history,
|
|
607
|
+
threadId: prompt.threadId,
|
|
608
|
+
runCount: prompt.runCount,
|
|
609
|
+
lastRunAt: prompt.lastRunAt?.toISOString() ?? null,
|
|
610
|
+
lastRunStatus: prompt.lastRunStatus,
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
next(error);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
//# sourceMappingURL=scheduled-prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduled-prompts.js","sourceRoot":"","sources":["../../src/api/scheduled-prompts.ts"],"names":[],"mappings":"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"}
|