@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.
Files changed (189) hide show
  1. package/dist/api/admin.js +438 -0
  2. package/dist/api/admin.js.map +1 -0
  3. package/dist/api/agents.js +21 -0
  4. package/dist/api/agents.js.map +1 -0
  5. package/dist/api/api-keys.js +122 -0
  6. package/dist/api/api-keys.js.map +1 -0
  7. package/dist/api/auth.js +399 -0
  8. package/dist/api/auth.js.map +1 -0
  9. package/dist/api/chat.js +900 -0
  10. package/dist/api/chat.js.map +1 -0
  11. package/dist/api/config.js +91 -0
  12. package/dist/api/config.js.map +1 -0
  13. package/dist/api/documents.js +237 -0
  14. package/dist/api/documents.js.map +1 -0
  15. package/dist/api/export.js +107 -0
  16. package/dist/api/export.js.map +1 -0
  17. package/dist/api/health.js +25 -0
  18. package/dist/api/health.js.map +1 -0
  19. package/dist/api/mcp-server.js +84 -0
  20. package/dist/api/mcp-server.js.map +1 -0
  21. package/dist/api/mcp.js +400 -0
  22. package/dist/api/mcp.js.map +1 -0
  23. package/dist/api/mentions.js +94 -0
  24. package/dist/api/mentions.js.map +1 -0
  25. package/dist/api/oauth.js +366 -0
  26. package/dist/api/oauth.js.map +1 -0
  27. package/dist/api/payments.js +473 -0
  28. package/dist/api/payments.js.map +1 -0
  29. package/dist/api/projects.js +301 -0
  30. package/dist/api/projects.js.map +1 -0
  31. package/dist/api/scheduled-prompts.js +617 -0
  32. package/dist/api/scheduled-prompts.js.map +1 -0
  33. package/dist/api/search.js +85 -0
  34. package/dist/api/search.js.map +1 -0
  35. package/dist/api/share.js +188 -0
  36. package/dist/api/share.js.map +1 -0
  37. package/dist/api/slack.js +468 -0
  38. package/dist/api/slack.js.map +1 -0
  39. package/dist/api/teams.js +693 -0
  40. package/dist/api/teams.js.map +1 -0
  41. package/dist/api/templates.js +134 -0
  42. package/dist/api/templates.js.map +1 -0
  43. package/dist/api/threads.js +323 -0
  44. package/dist/api/threads.js.map +1 -0
  45. package/dist/api/upload.js +57 -0
  46. package/dist/api/upload.js.map +1 -0
  47. package/dist/api/user.js +111 -0
  48. package/dist/api/user.js.map +1 -0
  49. package/dist/api/v1/openai.js +245 -0
  50. package/dist/api/v1/openai.js.map +1 -0
  51. package/dist/app.js +168 -0
  52. package/dist/app.js.map +1 -0
  53. package/dist/bin/cli.js +57 -0
  54. package/dist/bin/cli.js.map +1 -0
  55. package/dist/commands/db-sync.js +108 -0
  56. package/dist/commands/db-sync.js.map +1 -0
  57. package/dist/config/loader.js +374 -0
  58. package/dist/config/loader.js.map +1 -0
  59. package/dist/documents/extractors.js +136 -0
  60. package/dist/documents/extractors.js.map +1 -0
  61. package/dist/extensions/glob.js +53 -0
  62. package/dist/extensions/glob.js.map +1 -0
  63. package/dist/extensions/loader.js +72 -0
  64. package/dist/extensions/loader.js.map +1 -0
  65. package/dist/index.js +25 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/loaders/index.js +75 -0
  68. package/dist/loaders/index.js.map +1 -0
  69. package/dist/mcp/client.js +551 -0
  70. package/dist/mcp/client.js.map +1 -0
  71. package/dist/mcp/server.js +335 -0
  72. package/dist/mcp/server.js.map +1 -0
  73. package/dist/middleware/apiKeyAuth.js +136 -0
  74. package/dist/middleware/apiKeyAuth.js.map +1 -0
  75. package/dist/middleware/auth.js +192 -0
  76. package/dist/middleware/auth.js.map +1 -0
  77. package/dist/middleware/errorHandler.js +41 -0
  78. package/dist/middleware/errorHandler.js.map +1 -0
  79. package/dist/middleware/mcpServerAuth.js +164 -0
  80. package/dist/middleware/mcpServerAuth.js.map +1 -0
  81. package/dist/middleware/requestLogger.js +9 -0
  82. package/dist/middleware/requestLogger.js.map +1 -0
  83. package/dist/middleware/team.js +132 -0
  84. package/dist/middleware/team.js.map +1 -0
  85. package/dist/oauth/server.js +410 -0
  86. package/dist/oauth/server.js.map +1 -0
  87. package/dist/queue/cli.js +93 -0
  88. package/dist/queue/cli.js.map +1 -0
  89. package/dist/queue/handlers/index.js +91 -0
  90. package/dist/queue/handlers/index.js.map +1 -0
  91. package/dist/queue/handlers/scheduled-prompt.js +270 -0
  92. package/dist/queue/handlers/scheduled-prompt.js.map +1 -0
  93. package/dist/queue/index.js +91 -0
  94. package/dist/queue/index.js.map +1 -0
  95. package/dist/queue/providers/memory.js +296 -0
  96. package/dist/queue/providers/memory.js.map +1 -0
  97. package/dist/queue/providers/sqs.js +275 -0
  98. package/dist/queue/providers/sqs.js.map +1 -0
  99. package/dist/queue/scheduler.js +355 -0
  100. package/dist/queue/scheduler.js.map +1 -0
  101. package/dist/queue/types.js +5 -0
  102. package/dist/queue/types.js.map +1 -0
  103. package/dist/queue/worker.js +230 -0
  104. package/dist/queue/worker.js.map +1 -0
  105. package/dist/registry/index.js +40 -0
  106. package/dist/registry/index.js.map +1 -0
  107. package/dist/server.js +207 -0
  108. package/dist/server.js.map +1 -0
  109. package/dist/services/agent.js +530 -0
  110. package/dist/services/agent.js.map +1 -0
  111. package/dist/services/agents.js +194 -0
  112. package/dist/services/agents.js.map +1 -0
  113. package/dist/services/documents.js +507 -0
  114. package/dist/services/documents.js.map +1 -0
  115. package/dist/services/email/index.js +91 -0
  116. package/dist/services/email/index.js.map +1 -0
  117. package/dist/services/email/providers/ses.js +97 -0
  118. package/dist/services/email/providers/ses.js.map +1 -0
  119. package/dist/services/email/templates.js +194 -0
  120. package/dist/services/email/templates.js.map +1 -0
  121. package/dist/services/email/types.js +5 -0
  122. package/dist/services/email/types.js.map +1 -0
  123. package/dist/services/encryption.js +69 -0
  124. package/dist/services/encryption.js.map +1 -0
  125. package/dist/services/oauth-discovery.js +226 -0
  126. package/dist/services/oauth-discovery.js.map +1 -0
  127. package/dist/services/pendingConfirmation.js +105 -0
  128. package/dist/services/pendingConfirmation.js.map +1 -0
  129. package/dist/services/scheduledPrompts.js +70 -0
  130. package/dist/services/scheduledPrompts.js.map +1 -0
  131. package/dist/services/slack/client.js +174 -0
  132. package/dist/services/slack/client.js.map +1 -0
  133. package/dist/services/slack/events.js +189 -0
  134. package/dist/services/slack/events.js.map +1 -0
  135. package/dist/services/slack/index.js +6 -0
  136. package/dist/services/slack/index.js.map +1 -0
  137. package/dist/services/slack/notifications.js +124 -0
  138. package/dist/services/slack/notifications.js.map +1 -0
  139. package/dist/services/slack/signature.js +74 -0
  140. package/dist/services/slack/signature.js.map +1 -0
  141. package/dist/services/slack/thread-context.js +191 -0
  142. package/dist/services/slack/thread-context.js.map +1 -0
  143. package/dist/services/toolConfirmation.js +55 -0
  144. package/dist/services/toolConfirmation.js.map +1 -0
  145. package/dist/services/usage.js +241 -0
  146. package/dist/services/usage.js.map +1 -0
  147. package/dist/ssr/build.js +90 -0
  148. package/dist/ssr/build.js.map +1 -0
  149. package/dist/ssr/components/SSRMessageList.js +120 -0
  150. package/dist/ssr/components/SSRMessageList.js.map +1 -0
  151. package/dist/ssr/entry.client.js +8 -0
  152. package/dist/ssr/entry.client.js.map +1 -0
  153. package/dist/ssr/entry.server.js +71 -0
  154. package/dist/ssr/entry.server.js.map +1 -0
  155. package/dist/ssr/handler.js +51 -0
  156. package/dist/ssr/handler.js.map +1 -0
  157. package/dist/ssr/root.js +184 -0
  158. package/dist/ssr/root.js.map +1 -0
  159. package/dist/ssr/routes/login.js +140 -0
  160. package/dist/ssr/routes/login.js.map +1 -0
  161. package/dist/ssr/routes/pricing.js +195 -0
  162. package/dist/ssr/routes/pricing.js.map +1 -0
  163. package/dist/ssr/routes/privacy.js +39 -0
  164. package/dist/ssr/routes/privacy.js.map +1 -0
  165. package/dist/ssr/routes/register.js +148 -0
  166. package/dist/ssr/routes/register.js.map +1 -0
  167. package/dist/ssr/routes/shared.$shareId.js +153 -0
  168. package/dist/ssr/routes/shared.$shareId.js.map +1 -0
  169. package/dist/ssr/routes/terms.js +39 -0
  170. package/dist/ssr/routes/terms.js.map +1 -0
  171. package/dist/storage/index.js +43 -0
  172. package/dist/storage/index.js.map +1 -0
  173. package/dist/storage/providers/database.js +38 -0
  174. package/dist/storage/providers/database.js.map +1 -0
  175. package/dist/storage/providers/filesystem.js +51 -0
  176. package/dist/storage/providers/filesystem.js.map +1 -0
  177. package/dist/storage/types.js +2 -0
  178. package/dist/storage/types.js.map +1 -0
  179. package/dist/tools/documents.js +336 -0
  180. package/dist/tools/documents.js.map +1 -0
  181. package/dist/tools/get-plan-usage.js +82 -0
  182. package/dist/tools/get-plan-usage.js.map +1 -0
  183. package/dist/tools/index.js +106 -0
  184. package/dist/tools/index.js.map +1 -0
  185. package/dist/tools/types.js +2 -0
  186. package/dist/tools/types.js.map +1 -0
  187. package/dist/tools/web-scrape.js +145 -0
  188. package/dist/tools/web-scrape.js.map +1 -0
  189. 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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"}