instar 0.24.13 → 0.24.14

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 (90) hide show
  1. package/.claude/skills/setup-wizard/skill.md +281 -5
  2. package/dashboard/index.html +341 -0
  3. package/dist/cli.js +18 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/server.d.ts.map +1 -1
  6. package/dist/commands/server.js +188 -1
  7. package/dist/commands/server.js.map +1 -1
  8. package/dist/commands/slack-cli.d.ts +16 -0
  9. package/dist/commands/slack-cli.d.ts.map +1 -0
  10. package/dist/commands/slack-cli.js +198 -0
  11. package/dist/commands/slack-cli.js.map +1 -0
  12. package/dist/core/AgentRegistry.d.ts.map +1 -1
  13. package/dist/core/AgentRegistry.js +24 -6
  14. package/dist/core/AgentRegistry.js.map +1 -1
  15. package/dist/core/SleepWakeDetector.d.ts +11 -0
  16. package/dist/core/SleepWakeDetector.d.ts.map +1 -1
  17. package/dist/core/SleepWakeDetector.js +16 -1
  18. package/dist/core/SleepWakeDetector.js.map +1 -1
  19. package/dist/lifeline/ServerSupervisor.d.ts +13 -0
  20. package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
  21. package/dist/lifeline/ServerSupervisor.js +129 -0
  22. package/dist/lifeline/ServerSupervisor.js.map +1 -1
  23. package/dist/messaging/SessionSummarySentinel.js +1 -1
  24. package/dist/messaging/TelegramAdapter.d.ts +1 -0
  25. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  26. package/dist/messaging/TelegramAdapter.js +4 -1
  27. package/dist/messaging/TelegramAdapter.js.map +1 -1
  28. package/dist/messaging/slack/ChannelManager.d.ts +36 -0
  29. package/dist/messaging/slack/ChannelManager.d.ts.map +1 -0
  30. package/dist/messaging/slack/ChannelManager.js +100 -0
  31. package/dist/messaging/slack/ChannelManager.js.map +1 -0
  32. package/dist/messaging/slack/FileHandler.d.ts +30 -0
  33. package/dist/messaging/slack/FileHandler.d.ts.map +1 -0
  34. package/dist/messaging/slack/FileHandler.js +87 -0
  35. package/dist/messaging/slack/FileHandler.js.map +1 -0
  36. package/dist/messaging/slack/RingBuffer.d.ts +22 -0
  37. package/dist/messaging/slack/RingBuffer.d.ts.map +1 -0
  38. package/dist/messaging/slack/RingBuffer.js +48 -0
  39. package/dist/messaging/slack/RingBuffer.js.map +1 -0
  40. package/dist/messaging/slack/SlackAdapter.d.ts +136 -0
  41. package/dist/messaging/slack/SlackAdapter.d.ts.map +1 -0
  42. package/dist/messaging/slack/SlackAdapter.js +572 -0
  43. package/dist/messaging/slack/SlackAdapter.js.map +1 -0
  44. package/dist/messaging/slack/SlackApiClient.d.ts +51 -0
  45. package/dist/messaging/slack/SlackApiClient.d.ts.map +1 -0
  46. package/dist/messaging/slack/SlackApiClient.js +94 -0
  47. package/dist/messaging/slack/SlackApiClient.js.map +1 -0
  48. package/dist/messaging/slack/SocketModeClient.d.ts +44 -0
  49. package/dist/messaging/slack/SocketModeClient.d.ts.map +1 -0
  50. package/dist/messaging/slack/SocketModeClient.js +209 -0
  51. package/dist/messaging/slack/SocketModeClient.js.map +1 -0
  52. package/dist/messaging/slack/index.d.ts +12 -0
  53. package/dist/messaging/slack/index.d.ts.map +1 -0
  54. package/dist/messaging/slack/index.js +15 -0
  55. package/dist/messaging/slack/index.js.map +1 -0
  56. package/dist/messaging/slack/sanitize.d.ts +39 -0
  57. package/dist/messaging/slack/sanitize.d.ts.map +1 -0
  58. package/dist/messaging/slack/sanitize.js +71 -0
  59. package/dist/messaging/slack/sanitize.js.map +1 -0
  60. package/dist/messaging/slack/types.d.ts +155 -0
  61. package/dist/messaging/slack/types.d.ts.map +1 -0
  62. package/dist/messaging/slack/types.js +54 -0
  63. package/dist/messaging/slack/types.js.map +1 -0
  64. package/dist/monitoring/PresenceProxy.d.ts +157 -0
  65. package/dist/monitoring/PresenceProxy.d.ts.map +1 -0
  66. package/dist/monitoring/PresenceProxy.js +891 -0
  67. package/dist/monitoring/PresenceProxy.js.map +1 -0
  68. package/dist/monitoring/SessionWatchdog.d.ts.map +1 -1
  69. package/dist/monitoring/SessionWatchdog.js +2 -0
  70. package/dist/monitoring/SessionWatchdog.js.map +1 -1
  71. package/dist/server/AgentServer.d.ts +1 -0
  72. package/dist/server/AgentServer.d.ts.map +1 -1
  73. package/dist/server/AgentServer.js +49 -47
  74. package/dist/server/AgentServer.js.map +1 -1
  75. package/dist/server/routes.d.ts +1 -0
  76. package/dist/server/routes.d.ts.map +1 -1
  77. package/dist/server/routes.js +213 -4
  78. package/dist/server/routes.js.map +1 -1
  79. package/package.json +1 -1
  80. package/src/data/builtin-manifest.json +94 -78
  81. package/src/templates/hooks/slack-channel-context.sh +98 -0
  82. package/src/templates/scripts/slack-reply.sh +64 -0
  83. package/upgrades/0.24.11.md +23 -0
  84. package/upgrades/0.24.14.md +26 -0
  85. package/upgrades/0.24.6.md +20 -0
  86. package/upgrades/0.24.7.md +24 -0
  87. package/upgrades/0.24.8.md +19 -0
  88. package/upgrades/0.24.9.md +19 -0
  89. package/upgrades/NEXT.md +35 -0
  90. /package/.claude/skills/secret-setup/{skill.md → SKILL.md} +0 -0
@@ -0,0 +1,572 @@
1
+ /**
2
+ * SlackAdapter — Native Slack messaging adapter for Instar.
3
+ *
4
+ * Implements the MessagingAdapter interface using Socket Mode (WebSocket)
5
+ * for event intake and the Slack Web API for outbound messages.
6
+ *
7
+ * Key design decisions:
8
+ * - DIY app model (each user creates their own Slack app)
9
+ * - Socket Mode (no public URLs, no webhooks)
10
+ * - Zero external SDK (direct HTTP to Slack Web API)
11
+ * - authorizedUserIds is required and fail-closed
12
+ * - Ring buffer scoped to authorized users only
13
+ * - JSON-encoded context files (no delimiter-based injection)
14
+ */
15
+ import path from 'node:path';
16
+ import fs from 'node:fs';
17
+ import { SlackApiClient } from './SlackApiClient.js';
18
+ import { SocketModeClient } from './SocketModeClient.js';
19
+ import { ChannelManager } from './ChannelManager.js';
20
+ import { FileHandler } from './FileHandler.js';
21
+ import { RingBuffer } from './RingBuffer.js';
22
+ import { MessageLogger } from '../shared/MessageLogger.js';
23
+ import { sanitizeDisplayName } from './sanitize.js';
24
+ const RING_BUFFER_CAPACITY = 50;
25
+ const SLACK_MAX_TEXT_LENGTH = 4000;
26
+ const AUTO_ARCHIVE_DAYS = 7;
27
+ const LOG_PURGE_INTERVAL_MS = 24 * 60 * 60 * 1000; // Daily
28
+ export class SlackAdapter {
29
+ platform = 'slack';
30
+ // Config
31
+ config;
32
+ stateDir;
33
+ // Components
34
+ apiClient;
35
+ socketClient = null;
36
+ channelManager;
37
+ fileHandler;
38
+ logger;
39
+ // State
40
+ messageHandler = null;
41
+ started = false;
42
+ authorizedUsers;
43
+ channelHistory = new Map();
44
+ pendingPrompts = new Map();
45
+ userCache = new Map();
46
+ promptEvictionTimer = null;
47
+ housekeepingTimer = null;
48
+ logPurgeTimer = null;
49
+ // Callbacks (wired by server.ts)
50
+ /** Called when a prompt gate response is received */
51
+ onPromptResponse = null;
52
+ /** Called when a message is logged (for dual-write to SQLite) */
53
+ onMessageLogged = null;
54
+ constructor(config, stateDir) {
55
+ this.config = config;
56
+ this.stateDir = stateDir;
57
+ // Validate required fields
58
+ if (!this.config.botToken)
59
+ throw new Error('[slack] botToken is required');
60
+ if (!this.config.appToken)
61
+ throw new Error('[slack] appToken is required');
62
+ if (!Array.isArray(this.config.authorizedUserIds)) {
63
+ throw new Error('[slack] authorizedUserIds is required (array of Slack user IDs)');
64
+ }
65
+ // Fail-closed: empty array means deny all
66
+ this.authorizedUsers = new Set(this.config.authorizedUserIds);
67
+ if (this.authorizedUsers.size === 0) {
68
+ console.warn('[slack] authorizedUserIds is empty — all messages will be rejected (fail-closed)');
69
+ }
70
+ // Initialize components
71
+ this.apiClient = new SlackApiClient(this.config.botToken, this.config.appToken);
72
+ const agentName = this.config.workspaceName?.replace(/-agent$/, '') || 'agent';
73
+ this.channelManager = new ChannelManager(this.apiClient, agentName);
74
+ this.fileHandler = new FileHandler(this.apiClient, this.config.botToken, stateDir);
75
+ this.logger = new MessageLogger({
76
+ logPath: path.join(stateDir, 'slack-messages.jsonl'),
77
+ maxLines: 100_000,
78
+ keepLines: 75_000,
79
+ });
80
+ }
81
+ // ── MessagingAdapter Interface ──
82
+ async start() {
83
+ const handlers = {
84
+ onEvent: async (type, payload) => this._handleEvent(type, payload),
85
+ onInteraction: async (payload) => this._handleInteraction(payload),
86
+ onConnected: () => {
87
+ console.log('[slack] Socket Mode connected');
88
+ this.started = true;
89
+ },
90
+ onDisconnected: (reason) => {
91
+ console.log(`[slack] Disconnected: ${reason}`);
92
+ },
93
+ onError: (err, permanent) => {
94
+ if (permanent) {
95
+ console.error(`[slack] Permanent error: ${err.message}`);
96
+ }
97
+ else {
98
+ console.warn(`[slack] Transient error: ${err.message}`);
99
+ }
100
+ },
101
+ };
102
+ this.socketClient = new SocketModeClient(this.apiClient, handlers);
103
+ await this.socketClient.connect();
104
+ this.started = true;
105
+ // Start pending prompt TTL eviction
106
+ this._startPromptEviction();
107
+ // Start channel housekeeping (auto-archive idle channels)
108
+ this._startHousekeeping();
109
+ // Start log retention purge (daily)
110
+ this._startLogPurge();
111
+ // Purge stale log entries on startup
112
+ this._purgeOldLogs();
113
+ }
114
+ async stop() {
115
+ this.started = false;
116
+ if (this.promptEvictionTimer) {
117
+ clearInterval(this.promptEvictionTimer);
118
+ this.promptEvictionTimer = null;
119
+ }
120
+ if (this.housekeepingTimer) {
121
+ clearInterval(this.housekeepingTimer);
122
+ this.housekeepingTimer = null;
123
+ }
124
+ if (this.logPurgeTimer) {
125
+ clearInterval(this.logPurgeTimer);
126
+ this.logPurgeTimer = null;
127
+ }
128
+ if (this.socketClient) {
129
+ await this.socketClient.disconnect();
130
+ this.socketClient = null;
131
+ }
132
+ }
133
+ async send(message) {
134
+ const channelId = message.channel?.identifier;
135
+ if (!channelId) {
136
+ console.error('[slack] Cannot send: no channel identifier');
137
+ return;
138
+ }
139
+ // Chunk long messages
140
+ const chunks = this._chunkText(message.content);
141
+ let lastResult = null;
142
+ for (const chunk of chunks) {
143
+ const params = {
144
+ channel: channelId,
145
+ text: chunk,
146
+ };
147
+ // If there's thread_ts in metadata, reply in thread
148
+ if (message.channel?.type === 'slack' && message.threadTs) {
149
+ params.thread_ts = message.threadTs;
150
+ }
151
+ lastResult = await this.apiClient.call('chat.postMessage', params);
152
+ }
153
+ return lastResult;
154
+ }
155
+ onMessage(handler) {
156
+ this.messageHandler = handler;
157
+ }
158
+ async resolveUser(channelIdentifier) {
159
+ // For Slack, the channel identifier IS the user reference
160
+ return channelIdentifier || null;
161
+ }
162
+ // ── Slack-Specific Public Methods ──
163
+ /** Check if a user is authorized. */
164
+ isAuthorized(userId) {
165
+ return this.authorizedUsers.has(userId);
166
+ }
167
+ /** Send a message to a specific channel. */
168
+ async sendToChannel(channelId, text, options) {
169
+ const params = { channel: channelId, text };
170
+ if (options?.thread_ts)
171
+ params.thread_ts = options.thread_ts;
172
+ const result = await this.apiClient.call('chat.postMessage', params);
173
+ return result.ts;
174
+ }
175
+ /** Add a reaction (fire-and-forget). */
176
+ addReaction(channelId, timestamp, emoji) {
177
+ this.apiClient.call('reactions.add', { channel: channelId, timestamp, name: emoji }).catch(() => { });
178
+ }
179
+ /** Remove a reaction (fire-and-forget). */
180
+ removeReaction(channelId, timestamp, emoji) {
181
+ this.apiClient.call('reactions.remove', { channel: channelId, timestamp, name: emoji }).catch(() => { });
182
+ }
183
+ /** Update an existing message. */
184
+ async updateMessage(channelId, timestamp, text) {
185
+ await this.apiClient.call('chat.update', { channel: channelId, ts: timestamp, text });
186
+ }
187
+ /** Pin a message. */
188
+ async pinMessage(channelId, timestamp) {
189
+ await this.apiClient.call('pins.add', { channel: channelId, timestamp });
190
+ }
191
+ /** Send an ephemeral message (visible only to one user). */
192
+ async postEphemeral(channelId, userId, text) {
193
+ await this.apiClient.call('chat.postEphemeral', { channel: channelId, user: userId, text });
194
+ }
195
+ /** Send a message with Block Kit blocks. */
196
+ async sendBlocks(channelId, blocks, text) {
197
+ const params = { channel: channelId, blocks };
198
+ if (text)
199
+ params.text = text; // Fallback text for notifications
200
+ const result = await this.apiClient.call('chat.postMessage', params);
201
+ return result.ts;
202
+ }
203
+ /** Get cached channel messages from ring buffer. */
204
+ getChannelMessages(channelId, limit = 30) {
205
+ const buffer = this.channelHistory.get(channelId);
206
+ if (!buffer)
207
+ return [];
208
+ const all = buffer.toArray();
209
+ return limit >= all.length ? all : all.slice(-limit);
210
+ }
211
+ /** Get user info (cached for 5 minutes). */
212
+ async getUserInfo(userId) {
213
+ const cached = this.userCache.get(userId);
214
+ if (cached && Date.now() - cached.fetchedAt < 5 * 60 * 1000) {
215
+ return { id: userId, name: cached.name };
216
+ }
217
+ const result = await this.apiClient.call('users.info', { user: userId });
218
+ const user = result.user;
219
+ const name = user.real_name || user.name;
220
+ this.userCache.set(userId, { name, fetchedAt: Date.now() });
221
+ return { id: userId, name };
222
+ }
223
+ /** Create a channel. */
224
+ async createChannel(name, isPrivate) {
225
+ return this.channelManager.createChannel(name, isPrivate);
226
+ }
227
+ /** Archive a channel. */
228
+ async archiveChannel(channelId) {
229
+ return this.channelManager.archiveChannel(channelId);
230
+ }
231
+ /** Upload a file. */
232
+ async uploadFile(channelId, filePath, title) {
233
+ return this.fileHandler.uploadFile(channelId, filePath, title);
234
+ }
235
+ /** Download a file. */
236
+ async downloadFile(url, destPath) {
237
+ return this.fileHandler.downloadFile(url, destPath);
238
+ }
239
+ /** Get the underlying API client (for routes). */
240
+ get api() {
241
+ return this.apiClient;
242
+ }
243
+ // ── Test Helpers (underscore-prefixed) ──
244
+ /** Inject a simulated message for testing. */
245
+ async _testInjectMessage(event) {
246
+ await this._handleEvent('message', { event });
247
+ }
248
+ /** Inject a simulated interaction for testing. */
249
+ async _testInjectInteraction(payload) {
250
+ await this._handleInteraction(payload);
251
+ }
252
+ // ── Internal Event Handling ──
253
+ async _handleEvent(type, payload) {
254
+ const event = (payload.event ?? payload);
255
+ if (type === 'message' || event.type === 'message') {
256
+ await this._handleMessage(event);
257
+ }
258
+ else if (type === 'file_shared') {
259
+ await this._handleFileShared(event);
260
+ }
261
+ // reaction_added, app_mention can be handled later
262
+ }
263
+ async _handleMessage(event) {
264
+ const userId = event.user;
265
+ const text = event.text ?? '';
266
+ const channelId = event.channel;
267
+ const ts = event.ts;
268
+ const threadTs = event.thread_ts;
269
+ // Skip bot messages and subtypes (edits, deletes, etc.)
270
+ if (event.bot_id || event.subtype)
271
+ return;
272
+ if (!userId || !channelId)
273
+ return;
274
+ // AuthGate — fail-closed
275
+ if (!this.isAuthorized(userId)) {
276
+ return; // Silently drop unauthorized messages
277
+ }
278
+ // Populate ring buffer (authorized messages only — prevents cache poisoning)
279
+ const buffer = this.channelHistory.get(channelId) ?? new RingBuffer(RING_BUFFER_CAPACITY);
280
+ buffer.push({ ts, user: userId, text, channel: channelId, thread_ts: threadTs });
281
+ this.channelHistory.set(channelId, buffer);
282
+ // Resolve user name
283
+ let senderName = userId;
284
+ try {
285
+ const info = await this.getUserInfo(userId);
286
+ senderName = info.name;
287
+ }
288
+ catch {
289
+ // Use userId as fallback
290
+ }
291
+ // Log inbound message
292
+ const logEntry = {
293
+ messageId: ts,
294
+ channelId,
295
+ text,
296
+ fromUser: true,
297
+ timestamp: new Date(parseFloat(ts) * 1000).toISOString(),
298
+ sessionName: null,
299
+ senderName: sanitizeDisplayName(senderName),
300
+ platformUserId: userId,
301
+ platform: 'slack',
302
+ };
303
+ this.logger.append(logEntry);
304
+ this.onMessageLogged?.(logEntry);
305
+ // Acknowledge with reaction (fire-and-forget)
306
+ this.addReaction(channelId, ts, 'eyes');
307
+ // Convert to Instar Message format
308
+ const message = {
309
+ id: `slack-${ts}`,
310
+ userId,
311
+ content: text,
312
+ channel: {
313
+ type: 'slack',
314
+ identifier: channelId,
315
+ },
316
+ receivedAt: new Date(parseFloat(ts) * 1000).toISOString(),
317
+ metadata: {
318
+ slackUserId: userId,
319
+ senderName: sanitizeDisplayName(senderName),
320
+ ts,
321
+ threadTs: threadTs,
322
+ channelId,
323
+ isDM: channelId.startsWith('D'),
324
+ },
325
+ };
326
+ // Route to handler
327
+ if (this.messageHandler) {
328
+ try {
329
+ await this.messageHandler(message);
330
+ }
331
+ catch (err) {
332
+ console.error('[slack] Message handler error:', err.message);
333
+ }
334
+ }
335
+ // Mark complete (replace eyes with checkmark)
336
+ this.removeReaction(channelId, ts, 'eyes');
337
+ this.addReaction(channelId, ts, 'white_check_mark');
338
+ }
339
+ async _handleInteraction(payload) {
340
+ const userId = payload.user?.id;
341
+ if (!userId)
342
+ return;
343
+ // AuthGate check
344
+ if (!this.isAuthorized(userId)) {
345
+ console.warn(`[slack] Unauthorized interaction from ${userId}`);
346
+ return;
347
+ }
348
+ const action = payload.actions?.[0];
349
+ if (!action)
350
+ return;
351
+ if (action.action_id.startsWith('prompt::')) {
352
+ const parts = action.action_id.split('::');
353
+ const promptId = parts[1];
354
+ // Validate this is a prompt we sent
355
+ const messageTs = payload.message?.ts;
356
+ if (!messageTs || !this.pendingPrompts.has(messageTs)) {
357
+ console.warn(`[slack] Interaction for unknown prompt ts: ${messageTs}`);
358
+ return;
359
+ }
360
+ this.pendingPrompts.delete(messageTs);
361
+ // Update message to show selection
362
+ if (payload.channel?.id && messageTs) {
363
+ await this.updateMessage(payload.channel.id, messageTs, `Answered: ${action.text?.text ?? action.value ?? 'selected'}`).catch(() => { });
364
+ }
365
+ }
366
+ }
367
+ async _handleFileShared(event) {
368
+ const userId = event.user_id ?? event.user;
369
+ // AuthGate — check before download (prevents disk exhaustion from unauthorized users)
370
+ if (!userId || !this.isAuthorized(userId)) {
371
+ return;
372
+ }
373
+ // File handling would download and route to session
374
+ // Full implementation depends on session injection patterns
375
+ }
376
+ // ── Prompt Gate ──
377
+ /** Register a pending prompt (for interaction validation). */
378
+ registerPendingPrompt(messageTs, promptId, channelId) {
379
+ this.pendingPrompts.set(messageTs, {
380
+ promptId,
381
+ channelId,
382
+ messageTs,
383
+ createdAt: Date.now(),
384
+ });
385
+ }
386
+ _startPromptEviction() {
387
+ const ttl = (this.config.promptGate?.relayTimeoutSeconds ?? 300) * 1000;
388
+ this.promptEvictionTimer = setInterval(() => {
389
+ const now = Date.now();
390
+ for (const [ts, prompt] of this.pendingPrompts) {
391
+ if (now - prompt.createdAt > ttl) {
392
+ this.pendingPrompts.delete(ts);
393
+ }
394
+ }
395
+ }, 60_000); // Check every 60s
396
+ }
397
+ // ── Utilities ──
398
+ // ── Prompt Gate (Block Kit) ──
399
+ /**
400
+ * Relay a prompt to the user via Block Kit interactive message.
401
+ * Registers the prompt for validation against spoofed button presses.
402
+ */
403
+ async relayPrompt(channelId, promptId, question, options) {
404
+ const blocks = [
405
+ {
406
+ type: 'section',
407
+ text: { type: 'mrkdwn', text: `*Agent needs your input:*\n${question}` },
408
+ },
409
+ {
410
+ type: 'actions',
411
+ elements: options.map((opt, i) => ({
412
+ type: 'button',
413
+ text: { type: 'plain_text', text: opt.label },
414
+ value: opt.value,
415
+ action_id: `prompt::${promptId}::${i}`,
416
+ ...(opt.primary ? { style: 'primary' } : {}),
417
+ })),
418
+ },
419
+ ];
420
+ const ts = await this.sendBlocks(channelId, blocks, question);
421
+ this.registerPendingPrompt(ts, promptId, channelId);
422
+ }
423
+ // ── Message Search ──
424
+ /** Search the JSONL message log. */
425
+ searchLog(params) {
426
+ return this.logger.search(params);
427
+ }
428
+ /** Get message log statistics. */
429
+ getLogStats() {
430
+ return this.logger.getStats();
431
+ }
432
+ // ── Channel Housekeeping ──
433
+ /**
434
+ * Auto-archive channels idle for more than AUTO_ARCHIVE_DAYS.
435
+ * Runs periodically. Only archives session channels (sess- prefix).
436
+ */
437
+ async _archiveIdleChannels() {
438
+ try {
439
+ const channels = await this.channelManager.listChannels();
440
+ const now = Date.now();
441
+ const threshold = AUTO_ARCHIVE_DAYS * 24 * 60 * 60 * 1000;
442
+ for (const channel of channels) {
443
+ // Only auto-archive session channels, not system/job channels
444
+ if (!channel.name.includes('-sess-') || channel.is_archived)
445
+ continue;
446
+ // Check last message time from ring buffer
447
+ const history = this.channelHistory.get(channel.id);
448
+ const lastMessage = history?.toArray().at(-1);
449
+ if (lastMessage) {
450
+ const lastTs = parseFloat(lastMessage.ts) * 1000;
451
+ if (now - lastTs > threshold) {
452
+ await this.channelManager.archiveChannel(channel.id);
453
+ console.log(`[slack] Auto-archived idle channel: ${channel.name}`);
454
+ }
455
+ }
456
+ }
457
+ }
458
+ catch (err) {
459
+ console.error('[slack] Channel housekeeping error:', err.message);
460
+ }
461
+ }
462
+ _startHousekeeping() {
463
+ // Run every 6 hours
464
+ this.housekeepingTimer = setInterval(() => {
465
+ this._archiveIdleChannels().catch(() => { });
466
+ }, 6 * 60 * 60 * 1000);
467
+ if (this.housekeepingTimer.unref)
468
+ this.housekeepingTimer.unref();
469
+ }
470
+ // ── Log Retention ──
471
+ /** Purge log entries older than logRetentionDays. */
472
+ _purgeOldLogs() {
473
+ const retentionDays = this.config.logRetentionDays ?? 90;
474
+ if (retentionDays === 0)
475
+ return; // Unlimited
476
+ const logPath = path.join(this.stateDir, 'slack-messages.jsonl');
477
+ if (!fs.existsSync(logPath))
478
+ return;
479
+ try {
480
+ const cutoff = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);
481
+ const content = fs.readFileSync(logPath, 'utf-8');
482
+ const lines = content.split('\n').filter(Boolean);
483
+ const kept = lines.filter(line => {
484
+ try {
485
+ const entry = JSON.parse(line);
486
+ return new Date(entry.timestamp) >= cutoff;
487
+ }
488
+ catch {
489
+ return true; // Keep unparseable lines
490
+ }
491
+ });
492
+ if (kept.length < lines.length) {
493
+ fs.writeFileSync(logPath, kept.join('\n') + '\n');
494
+ console.log(`[slack] Log purge: removed ${lines.length - kept.length} entries older than ${retentionDays} days`);
495
+ }
496
+ }
497
+ catch {
498
+ // Non-fatal — will retry on next cycle
499
+ }
500
+ }
501
+ _startLogPurge() {
502
+ this.logPurgeTimer = setInterval(() => {
503
+ this._purgeOldLogs();
504
+ }, LOG_PURGE_INTERVAL_MS);
505
+ if (this.logPurgeTimer.unref)
506
+ this.logPurgeTimer.unref();
507
+ }
508
+ // ── Dashboard ──
509
+ /**
510
+ * Broadcast the tunnel URL to the dashboard channel.
511
+ * Called by server.ts when tunnel is established.
512
+ */
513
+ async broadcastDashboardUrl(tunnelUrl) {
514
+ const dashboardChannelId = this.config.dashboardChannelId;
515
+ if (!dashboardChannelId)
516
+ return;
517
+ const text = `Dashboard available at: ${tunnelUrl}`;
518
+ try {
519
+ await this.sendToChannel(dashboardChannelId, text);
520
+ await this.pinMessage(dashboardChannelId, (await this.sendToChannel(dashboardChannelId, text)));
521
+ }
522
+ catch (err) {
523
+ console.error('[slack] Dashboard broadcast failed:', err.message);
524
+ }
525
+ }
526
+ // ── Unanswered Message Detection ──
527
+ /**
528
+ * Get count of unanswered user messages in a channel.
529
+ * A message is "unanswered" if it's from a user and no agent reply follows.
530
+ */
531
+ getUnansweredCount(channelId) {
532
+ const messages = this.getChannelMessages(channelId);
533
+ let unanswered = 0;
534
+ for (let i = messages.length - 1; i >= 0; i--) {
535
+ const msg = messages[i];
536
+ // Messages from authorized users are "user" messages
537
+ if (this.authorizedUsers.has(msg.user)) {
538
+ unanswered++;
539
+ }
540
+ else {
541
+ break; // Agent reply found — stop counting
542
+ }
543
+ }
544
+ return unanswered;
545
+ }
546
+ _chunkText(text) {
547
+ if (text.length <= SLACK_MAX_TEXT_LENGTH)
548
+ return [text];
549
+ const chunks = [];
550
+ let remaining = text;
551
+ while (remaining.length > 0) {
552
+ if (remaining.length <= SLACK_MAX_TEXT_LENGTH) {
553
+ chunks.push(remaining);
554
+ break;
555
+ }
556
+ // Try to break at a newline
557
+ let breakPoint = remaining.lastIndexOf('\n', SLACK_MAX_TEXT_LENGTH);
558
+ if (breakPoint < SLACK_MAX_TEXT_LENGTH / 2) {
559
+ // No good newline break — try space
560
+ breakPoint = remaining.lastIndexOf(' ', SLACK_MAX_TEXT_LENGTH);
561
+ }
562
+ if (breakPoint < SLACK_MAX_TEXT_LENGTH / 2) {
563
+ // No good break point — hard break
564
+ breakPoint = SLACK_MAX_TEXT_LENGTH;
565
+ }
566
+ chunks.push(remaining.slice(0, breakPoint));
567
+ remaining = remaining.slice(breakPoint).trimStart();
568
+ }
569
+ return chunks;
570
+ }
571
+ }
572
+ //# sourceMappingURL=SlackAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackAdapter.js","sourceRoot":"","sources":["../../../src/messaging/slack/SlackAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * SlackApiClient — Zero-SDK HTTP client for the Slack Web API.
3
+ *
4
+ * All Slack API calls go through this class, which handles:
5
+ * - Authentication (bot token vs app token)
6
+ * - Rate limit detection and retry (Retry-After header)
7
+ * - Error classification (permanent vs transient)
8
+ * - Token redaction in logs
9
+ */
10
+ import { type RateLimitTier } from './types.js';
11
+ export interface SlackApiOptions {
12
+ /** Use app-level token instead of bot token */
13
+ useAppToken?: boolean;
14
+ /** Max retries on rate limit (default: 3) */
15
+ maxRetries?: number;
16
+ }
17
+ export interface SlackApiResponse {
18
+ ok: boolean;
19
+ error?: string;
20
+ response_metadata?: {
21
+ next_cursor?: string;
22
+ retry_after?: number;
23
+ };
24
+ [key: string]: unknown;
25
+ }
26
+ export declare class SlackApiClient {
27
+ private botToken;
28
+ private appToken;
29
+ constructor(botToken: string, appToken?: string);
30
+ /**
31
+ * Call a Slack Web API method.
32
+ *
33
+ * @param method - API method name (e.g., 'chat.postMessage')
34
+ * @param params - JSON body parameters
35
+ * @param options - Token selection and retry options
36
+ * @returns Parsed JSON response
37
+ * @throws Error on non-ok response (after retries for rate limits)
38
+ */
39
+ call(method: string, params?: Record<string, unknown>, options?: SlackApiOptions): Promise<SlackApiResponse>;
40
+ /** Get the rate limit tier for a method. */
41
+ getTier(method: string): RateLimitTier;
42
+ private _callWithRetry;
43
+ }
44
+ /** Typed error for Slack API failures. */
45
+ export declare class SlackApiError extends Error {
46
+ readonly method: string;
47
+ readonly slackError: string;
48
+ readonly permanent: boolean;
49
+ constructor(message: string, method: string, slackError: string, permanent: boolean);
50
+ }
51
+ //# sourceMappingURL=SlackApiClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackApiClient.d.ts","sourceRoot":"","sources":["../../../src/messaging/slack/SlackApiClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAGzD,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAcD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAgB;gBAEpB,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAK/C;;;;;;;;OAQG;IACG,IAAI,CACR,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IAU5B,4CAA4C;IAC5C,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa;YAIxB,cAAc;CA8C7B;AAED,0CAA0C;AAC1C,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO;CAOpF"}