@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,105 @@
1
+ /**
2
+ * PendingConfirmationManager - Manages pending tool confirmations
3
+ *
4
+ * When a tool requires user confirmation, a pending confirmation is created
5
+ * that holds a promise resolver. The chat handler awaits this promise while
6
+ * the user is shown a confirmation modal. When the user responds via the
7
+ * /confirm-tool API, the promise resolves and the tool continues.
8
+ */
9
+ class PendingConfirmationManager {
10
+ pending = new Map();
11
+ cleanupInterval = null;
12
+ TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
13
+ constructor() {
14
+ // Start cleanup interval
15
+ this.cleanupInterval = setInterval(() => this.cleanup(), 60000); // Check every minute
16
+ }
17
+ /**
18
+ * Create a new pending confirmation
19
+ * Returns an id and a promise that resolves when the user responds
20
+ */
21
+ create(params) {
22
+ const id = `confirm_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
23
+ let resolveFunc;
24
+ const promise = new Promise((resolve) => {
25
+ resolveFunc = resolve;
26
+ });
27
+ const confirmation = {
28
+ id,
29
+ visitorId: params.visitorId,
30
+ threadId: params.threadId,
31
+ userId: params.userId,
32
+ serverId: params.serverId,
33
+ toolName: params.toolName,
34
+ toolArgs: params.toolArgs,
35
+ resolve: resolveFunc,
36
+ createdAt: Date.now(),
37
+ };
38
+ this.pending.set(id, confirmation);
39
+ console.log(`[PendingConfirmation] Created: ${id} for tool ${params.serverId}:${params.toolName}`);
40
+ return { id, promise };
41
+ }
42
+ /**
43
+ * Resolve a pending confirmation
44
+ * Called when the user responds to the confirmation modal
45
+ */
46
+ resolve(id, approved, scope) {
47
+ const confirmation = this.pending.get(id);
48
+ if (!confirmation) {
49
+ console.log(`[PendingConfirmation] Not found: ${id}`);
50
+ return false;
51
+ }
52
+ console.log(`[PendingConfirmation] Resolved: ${id} approved=${approved} scope=${scope}`);
53
+ confirmation.resolve({ approved, scope });
54
+ this.pending.delete(id);
55
+ return true;
56
+ }
57
+ /**
58
+ * Get a pending confirmation by ID
59
+ */
60
+ get(id) {
61
+ return this.pending.get(id);
62
+ }
63
+ /**
64
+ * Clean up expired confirmations (5 minute timeout)
65
+ * Expired confirmations are auto-denied
66
+ */
67
+ cleanup() {
68
+ const now = Date.now();
69
+ const expiredIds = [];
70
+ for (const [id, confirmation] of this.pending.entries()) {
71
+ if (now - confirmation.createdAt > this.TIMEOUT_MS) {
72
+ expiredIds.push(id);
73
+ }
74
+ }
75
+ for (const id of expiredIds) {
76
+ const confirmation = this.pending.get(id);
77
+ if (confirmation) {
78
+ console.log(`[PendingConfirmation] Expired: ${id}`);
79
+ confirmation.resolve({ approved: false }); // Auto-deny expired confirmations
80
+ this.pending.delete(id);
81
+ }
82
+ }
83
+ if (expiredIds.length > 0) {
84
+ console.log(`[PendingConfirmation] Cleaned up ${expiredIds.length} expired confirmations`);
85
+ }
86
+ }
87
+ /**
88
+ * Get count of pending confirmations (for monitoring)
89
+ */
90
+ getPendingCount() {
91
+ return this.pending.size;
92
+ }
93
+ /**
94
+ * Shutdown - cleanup interval
95
+ */
96
+ shutdown() {
97
+ if (this.cleanupInterval) {
98
+ clearInterval(this.cleanupInterval);
99
+ this.cleanupInterval = null;
100
+ }
101
+ }
102
+ }
103
+ // Singleton instance
104
+ export const pendingConfirmations = new PendingConfirmationManager();
105
+ //# sourceMappingURL=pendingConfirmation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pendingConfirmation.js","sourceRoot":"","sources":["../../src/services/pendingConfirmation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Scheduled Prompts Service
3
+ *
4
+ * Manages scheduled prompts lifecycle and sync with recurring jobs.
5
+ */
6
+ import { db } from '@chaaskit/db';
7
+ import { getScheduler } from '../queue/index.js';
8
+ /**
9
+ * Sync all enabled scheduled prompts to recurring jobs.
10
+ * Called on server startup to ensure scheduler has all jobs.
11
+ *
12
+ * @returns Number of prompts synced
13
+ */
14
+ export async function syncScheduledPromptsToRecurringJobs() {
15
+ const scheduler = getScheduler();
16
+ if (!scheduler) {
17
+ console.log('[ScheduledPrompts] Scheduler not available');
18
+ return 0;
19
+ }
20
+ // Get all enabled scheduled prompts
21
+ const prompts = await db.scheduledPrompt.findMany({
22
+ where: { enabled: true },
23
+ });
24
+ console.log(`[ScheduledPrompts] Found ${prompts.length} enabled prompts to sync`);
25
+ for (const prompt of prompts) {
26
+ const recurringJobName = `scheduled-prompt:${prompt.id}`;
27
+ try {
28
+ await scheduler.registerRecurring({
29
+ name: recurringJobName,
30
+ type: 'scheduled-prompt:execute',
31
+ payload: { scheduledPromptId: prompt.id },
32
+ schedule: prompt.schedule,
33
+ timezone: prompt.timezone,
34
+ });
35
+ }
36
+ catch (error) {
37
+ console.error(`[ScheduledPrompts] Failed to sync prompt ${prompt.id}:`, error instanceof Error ? error.message : error);
38
+ }
39
+ }
40
+ // Clean up orphaned recurring jobs (prompts that were deleted while server was down)
41
+ const allRecurringJobs = await db.recurringJob.findMany({
42
+ where: {
43
+ name: { startsWith: 'scheduled-prompt:' },
44
+ },
45
+ });
46
+ const promptIds = new Set(prompts.map((p) => p.id));
47
+ for (const job of allRecurringJobs) {
48
+ const promptId = job.name.replace('scheduled-prompt:', '');
49
+ if (!promptIds.has(promptId)) {
50
+ console.log(`[ScheduledPrompts] Cleaning up orphaned job: ${job.name}`);
51
+ await db.recurringJob.delete({
52
+ where: { id: job.id },
53
+ }).catch(() => {
54
+ // Ignore deletion errors
55
+ });
56
+ }
57
+ }
58
+ // Also disable recurring jobs for disabled prompts
59
+ const disabledPrompts = await db.scheduledPrompt.findMany({
60
+ where: { enabled: false },
61
+ });
62
+ for (const prompt of disabledPrompts) {
63
+ const recurringJobName = `scheduled-prompt:${prompt.id}`;
64
+ await scheduler.disableRecurring(recurringJobName).catch(() => {
65
+ // Ignore if job doesn't exist
66
+ });
67
+ }
68
+ return prompts.length;
69
+ }
70
+ //# sourceMappingURL=scheduledPrompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduledPrompts.js","sourceRoot":"","sources":["../../src/services/scheduledPrompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,174 @@
1
+ import { getConfig } from '../../config/loader.js';
2
+ import { decryptCredential, encryptCredential } from '../encryption.js';
3
+ /**
4
+ * Get Slack OAuth credentials from environment.
5
+ */
6
+ export function getSlackCredentials() {
7
+ const config = getConfig();
8
+ const clientIdEnvVar = config.slack?.clientIdEnvVar || 'SLACK_CLIENT_ID';
9
+ const clientSecretEnvVar = config.slack?.clientSecretEnvVar || 'SLACK_CLIENT_SECRET';
10
+ const clientId = process.env[clientIdEnvVar];
11
+ const clientSecret = process.env[clientSecretEnvVar];
12
+ if (!clientId || !clientSecret) {
13
+ throw new Error(`Missing Slack credentials: ${clientIdEnvVar} or ${clientSecretEnvVar}`);
14
+ }
15
+ return { clientId, clientSecret };
16
+ }
17
+ /**
18
+ * Exchange OAuth code for access tokens.
19
+ */
20
+ export async function exchangeCodeForTokens(code, redirectUri) {
21
+ const { clientId, clientSecret } = getSlackCredentials();
22
+ const response = await fetch('https://slack.com/api/oauth.v2.access', {
23
+ method: 'POST',
24
+ headers: {
25
+ 'Content-Type': 'application/x-www-form-urlencoded',
26
+ },
27
+ body: new URLSearchParams({
28
+ client_id: clientId,
29
+ client_secret: clientSecret,
30
+ code,
31
+ redirect_uri: redirectUri,
32
+ }),
33
+ });
34
+ const data = await response.json();
35
+ return data;
36
+ }
37
+ /**
38
+ * Build Slack OAuth authorization URL.
39
+ */
40
+ export function buildOAuthUrl(state, redirectUri) {
41
+ const { clientId } = getSlackCredentials();
42
+ const scopes = [
43
+ 'app_mentions:read',
44
+ 'channels:history',
45
+ 'groups:history',
46
+ 'im:history',
47
+ 'chat:write',
48
+ 'reactions:write',
49
+ 'users:read',
50
+ ].join(',');
51
+ const params = new URLSearchParams({
52
+ client_id: clientId,
53
+ scope: scopes,
54
+ redirect_uri: redirectUri,
55
+ state,
56
+ });
57
+ return `https://slack.com/oauth/v2/authorize?${params.toString()}`;
58
+ }
59
+ /**
60
+ * Encrypt tokens for storage.
61
+ */
62
+ export function encryptTokens(tokens) {
63
+ return encryptCredential(tokens);
64
+ }
65
+ /**
66
+ * Decrypt stored tokens.
67
+ */
68
+ export function decryptTokens(encryptedTokens) {
69
+ return decryptCredential(encryptedTokens);
70
+ }
71
+ /**
72
+ * Slack API client class for making authenticated requests.
73
+ */
74
+ export class SlackClient {
75
+ botToken;
76
+ constructor(botToken) {
77
+ this.botToken = botToken;
78
+ }
79
+ /**
80
+ * Create client from encrypted tokens.
81
+ */
82
+ static fromEncrypted(encryptedTokens) {
83
+ const tokens = decryptTokens(encryptedTokens);
84
+ return new SlackClient(tokens.botToken);
85
+ }
86
+ /**
87
+ * Make an authenticated request to the Slack API.
88
+ */
89
+ async request(endpoint, options = {}) {
90
+ const url = `https://slack.com/api/${endpoint}`;
91
+ const response = await fetch(url, {
92
+ ...options,
93
+ headers: {
94
+ 'Authorization': `Bearer ${this.botToken}`,
95
+ 'Content-Type': 'application/json; charset=utf-8',
96
+ ...options.headers,
97
+ },
98
+ });
99
+ const data = await response.json();
100
+ return data;
101
+ }
102
+ /**
103
+ * Post a message to a channel.
104
+ */
105
+ async postMessage(channel, text, options = {}) {
106
+ return this.request('chat.postMessage', {
107
+ method: 'POST',
108
+ body: JSON.stringify({
109
+ channel,
110
+ text,
111
+ thread_ts: options.threadTs,
112
+ mrkdwn: options.mrkdwn ?? true,
113
+ unfurl_links: options.unfurlLinks ?? false,
114
+ unfurl_media: options.unfurlMedia ?? false,
115
+ }),
116
+ });
117
+ }
118
+ /**
119
+ * Add a reaction to a message.
120
+ */
121
+ async addReaction(channel, timestamp, emoji) {
122
+ return this.request('reactions.add', {
123
+ method: 'POST',
124
+ body: JSON.stringify({
125
+ channel,
126
+ timestamp,
127
+ name: emoji,
128
+ }),
129
+ });
130
+ }
131
+ /**
132
+ * Remove a reaction from a message.
133
+ */
134
+ async removeReaction(channel, timestamp, emoji) {
135
+ return this.request('reactions.remove', {
136
+ method: 'POST',
137
+ body: JSON.stringify({
138
+ channel,
139
+ timestamp,
140
+ name: emoji,
141
+ }),
142
+ });
143
+ }
144
+ /**
145
+ * Get conversation/thread history.
146
+ */
147
+ async getConversationHistory(channel, options = {}) {
148
+ const endpoint = options.threadTs ? 'conversations.replies' : 'conversations.history';
149
+ const params = {
150
+ channel,
151
+ limit: (options.limit ?? 50).toString(),
152
+ };
153
+ if (options.threadTs) {
154
+ params.ts = options.threadTs;
155
+ }
156
+ if (options.cursor) {
157
+ params.cursor = options.cursor;
158
+ }
159
+ return this.request(`${endpoint}?${new URLSearchParams(params).toString()}`);
160
+ }
161
+ /**
162
+ * Get user information.
163
+ */
164
+ async getUserInfo(userId) {
165
+ return this.request(`users.info?user=${userId}`);
166
+ }
167
+ /**
168
+ * Test authentication (useful for checking if token is valid).
169
+ */
170
+ async authTest() {
171
+ return this.request('auth.test', { method: 'POST' });
172
+ }
173
+ }
174
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/services/slack/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,189 @@
1
+ import { db } from '@chaaskit/db';
2
+ import { getConfig } from '../../config/loader.js';
3
+ import { createAgentService } from '../agent.js';
4
+ import { getDefaultAgent, toAgentConfig, isBuiltInAgent } from '../agents.js';
5
+ import { SlackClient } from './client.js';
6
+ import { buildSlackThreadContext, findOrCreateInternalThread, getInternalThreadHistory, saveToInternalThread, cleanSlackMessage, formatForSlack, SLACK_FORMAT_INSTRUCTIONS, } from './thread-context.js';
7
+ /**
8
+ * Process a pending Slack event.
9
+ */
10
+ export async function processSlackEvent(eventId) {
11
+ // Atomic claim: UPDATE SET status='processing' WHERE id=? AND status='pending'
12
+ const event = await db.slackMessageEvent.findUnique({
13
+ where: { id: eventId },
14
+ include: {
15
+ integration: {
16
+ include: {
17
+ team: true,
18
+ },
19
+ },
20
+ },
21
+ });
22
+ if (!event) {
23
+ console.log('[Slack] Event not found:', eventId);
24
+ return;
25
+ }
26
+ // Atomic claim with WHERE status='pending'
27
+ const claimResult = await db.slackMessageEvent.updateMany({
28
+ where: {
29
+ id: eventId,
30
+ status: 'pending',
31
+ },
32
+ data: {
33
+ status: 'processing',
34
+ },
35
+ });
36
+ if (claimResult.count === 0) {
37
+ // Already claimed or not pending
38
+ console.log('[Slack] Event already claimed:', eventId);
39
+ return;
40
+ }
41
+ const integration = event.integration;
42
+ // Check if AI chat is enabled
43
+ const config = getConfig();
44
+ if (!config.slack?.aiChat?.enabled || !integration.aiChatEnabled) {
45
+ console.log('[Slack] AI chat disabled for this integration');
46
+ await markEventCompleted(eventId);
47
+ return;
48
+ }
49
+ try {
50
+ // Create Slack client
51
+ const client = SlackClient.fromEncrypted(integration.encryptedTokens);
52
+ // Add eyes reaction to indicate processing
53
+ try {
54
+ await client.addReaction(event.slackChannelId, event.slackMessageTs, 'eyes');
55
+ }
56
+ catch (err) {
57
+ // Non-critical, continue processing
58
+ console.warn('[Slack] Failed to add reaction:', err);
59
+ }
60
+ // Clean the incoming message
61
+ const cleanedMessage = cleanSlackMessage(event.messageText || '', integration.slackBotUserId);
62
+ if (!cleanedMessage) {
63
+ console.log('[Slack] Empty message after cleaning');
64
+ await markEventFailed(eventId, 'Empty message');
65
+ return;
66
+ }
67
+ // Build context from Slack thread (if in a thread)
68
+ let slackContext = await buildSlackThreadContext(client, event.slackChannelId, event.slackThreadTs, integration.slackBotUserId);
69
+ // Find or create internal thread for continuity
70
+ const internalThreadId = await findOrCreateInternalThread(integration.teamId, event.slackChannelId, event.slackThreadTs);
71
+ // Update event with internal thread linkage
72
+ await db.slackMessageEvent.update({
73
+ where: { id: eventId },
74
+ data: { internalThreadId },
75
+ });
76
+ // Get history from internal thread (for context continuity)
77
+ const internalHistory = await getInternalThreadHistory(internalThreadId);
78
+ // Build messages for agent
79
+ const messages = [];
80
+ // Use internal history if available (preferred for continuity)
81
+ if (config.slack?.aiChat?.threadContinuity && internalHistory.length > 0) {
82
+ messages.push(...internalHistory);
83
+ }
84
+ else if (slackContext && slackContext.messages.length > 0) {
85
+ // Fall back to Slack thread context
86
+ messages.push(...slackContext.messages);
87
+ }
88
+ // Add current message
89
+ messages.push({
90
+ role: 'user',
91
+ content: cleanedMessage,
92
+ });
93
+ // Save user message to internal thread
94
+ await saveToInternalThread(internalThreadId, 'user', cleanedMessage);
95
+ // Get the default agent
96
+ const agent = getDefaultAgent();
97
+ const agentConfig = toAgentConfig(agent);
98
+ // Get system prompt and add Slack formatting instructions
99
+ const baseSystemPrompt = isBuiltInAgent(agent) ? agent.systemPrompt : undefined;
100
+ const systemPrompt = baseSystemPrompt
101
+ ? `${baseSystemPrompt}\n\n${SLACK_FORMAT_INSTRUCTIONS}`
102
+ : SLACK_FORMAT_INSTRUCTIONS;
103
+ // Create agent service and generate response
104
+ const agentService = createAgentService(agentConfig);
105
+ // Collect the full response
106
+ let fullResponse = '';
107
+ const chunks = agentService.chat(messages, {
108
+ systemPrompt,
109
+ teamContext: integration.team?.context || null,
110
+ });
111
+ for await (const chunk of chunks) {
112
+ if (chunk.type === 'text' && chunk.content) {
113
+ fullResponse += chunk.content;
114
+ }
115
+ }
116
+ if (!fullResponse.trim()) {
117
+ console.log('[Slack] Empty response from agent');
118
+ await markEventFailed(eventId, 'Empty response from agent');
119
+ return;
120
+ }
121
+ // Format response for Slack
122
+ const formattedResponse = formatForSlack(fullResponse);
123
+ // Save assistant response to internal thread
124
+ await saveToInternalThread(internalThreadId, 'assistant', fullResponse);
125
+ // Post response to Slack
126
+ const threadTs = event.slackThreadTs || event.slackMessageTs; // Reply in thread
127
+ const postResult = await client.postMessage(event.slackChannelId, formattedResponse, { threadTs });
128
+ if (!postResult.ok) {
129
+ console.error('[Slack] Failed to post message:', postResult.error);
130
+ await markEventFailed(eventId, `Failed to post: ${postResult.error}`);
131
+ // Try to add error reaction
132
+ try {
133
+ await client.removeReaction(event.slackChannelId, event.slackMessageTs, 'eyes');
134
+ await client.addReaction(event.slackChannelId, event.slackMessageTs, 'x');
135
+ }
136
+ catch { }
137
+ return;
138
+ }
139
+ // Replace eyes with checkmark
140
+ try {
141
+ await client.removeReaction(event.slackChannelId, event.slackMessageTs, 'eyes');
142
+ await client.addReaction(event.slackChannelId, event.slackMessageTs, 'white_check_mark');
143
+ }
144
+ catch (err) {
145
+ // Non-critical
146
+ console.warn('[Slack] Failed to update reaction:', err);
147
+ }
148
+ // Mark event as completed
149
+ await db.slackMessageEvent.update({
150
+ where: { id: eventId },
151
+ data: {
152
+ status: 'completed',
153
+ processedAt: new Date(),
154
+ responseTs: postResult.ts,
155
+ },
156
+ });
157
+ console.log('[Slack] Successfully processed event:', eventId);
158
+ }
159
+ catch (error) {
160
+ console.error('[Slack] Error processing event:', error);
161
+ await markEventFailed(eventId, error instanceof Error ? error.message : 'Unknown error');
162
+ // Try to add error reaction
163
+ try {
164
+ const client = SlackClient.fromEncrypted(integration.encryptedTokens);
165
+ await client.removeReaction(event.slackChannelId, event.slackMessageTs, 'eyes');
166
+ await client.addReaction(event.slackChannelId, event.slackMessageTs, 'x');
167
+ }
168
+ catch { }
169
+ }
170
+ }
171
+ async function markEventCompleted(eventId) {
172
+ await db.slackMessageEvent.update({
173
+ where: { id: eventId },
174
+ data: {
175
+ status: 'completed',
176
+ processedAt: new Date(),
177
+ },
178
+ });
179
+ }
180
+ async function markEventFailed(eventId, error) {
181
+ await db.slackMessageEvent.update({
182
+ where: { id: eventId },
183
+ data: {
184
+ status: 'failed',
185
+ lastError: error,
186
+ },
187
+ });
188
+ }
189
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/services/slack/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from './signature.js';
2
+ export * from './client.js';
3
+ export * from './events.js';
4
+ export * from './thread-context.js';
5
+ export * from './notifications.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/slack/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}