@geminixiang/mama 0.2.0-beta.4 → 0.2.0-beta.5
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/README.md +100 -421
- package/dist/adapter.d.ts +9 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +1 -0
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +4 -1
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +9 -2
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +1 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +9 -3
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +13 -3
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +9 -2
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +13 -5
- package/dist/agent.js.map +1 -1
- package/dist/bindings.d.ts +2 -1
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js.map +1 -1
- package/dist/commands/index.d.ts +5 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +8 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/login.d.ts +5 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +37 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/registry.d.ts +7 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +14 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/session-view.d.ts +5 -0
- package/dist/commands/session-view.d.ts.map +1 -0
- package/dist/commands/session-view.js +38 -0
- package/dist/commands/session-view.js.map +1 -0
- package/dist/commands/types.d.ts +41 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/utils.d.ts +5 -0
- package/dist/commands/utils.d.ts.map +1 -0
- package/dist/commands/utils.js +9 -0
- package/dist/commands/utils.js.map +1 -0
- package/dist/config.d.ts +4 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -40
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +74 -68
- package/dist/context.js.map +1 -1
- package/dist/execution-resolver.d.ts +6 -3
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +47 -14
- package/dist/execution-resolver.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +2 -3
- package/dist/instrument.js.map +1 -1
- package/dist/login/index.d.ts.map +1 -1
- package/dist/login/index.js +19 -8
- package/dist/login/index.js.map +1 -1
- package/dist/login/portal.d.ts.map +1 -1
- package/dist/login/portal.js +7 -7
- package/dist/login/portal.js.map +1 -1
- package/dist/login/session.d.ts +3 -2
- package/dist/login/session.d.ts.map +1 -1
- package/dist/login/session.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +62 -386
- package/dist/main.js.map +1 -1
- package/dist/provisioner.d.ts +11 -9
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +125 -87
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/session-runtime.d.ts +26 -0
- package/dist/runtime/session-runtime.d.ts.map +1 -0
- package/dist/runtime/session-runtime.js +285 -0
- package/dist/runtime/session-runtime.js.map +1 -0
- package/dist/sandbox/cloudflare.d.ts +14 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -0
- package/dist/sandbox/cloudflare.js +131 -0
- package/dist/sandbox/cloudflare.js.map +1 -0
- package/dist/sandbox/index.d.ts +6 -4
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +6 -3
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +5 -1
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/session-view/portal.d.ts.map +1 -1
- package/dist/session-view/portal.js +10 -1
- package/dist/session-view/portal.js.map +1 -1
- package/dist/session-view/service.d.ts.map +1 -1
- package/dist/session-view/service.js +36 -26
- package/dist/session-view/service.js.map +1 -1
- package/dist/session-view/store.d.ts +3 -2
- package/dist/session-view/store.d.ts.map +1 -1
- package/dist/session-view/store.js.map +1 -1
- package/dist/vault-routing.d.ts +3 -5
- package/dist/vault-routing.d.ts.map +1 -1
- package/dist/vault-routing.js +8 -20
- package/dist/vault-routing.js.map +1 -1
- package/dist/vault.d.ts +7 -5
- package/dist/vault.d.ts.map +1 -1
- package/dist/vault.js +101 -50
- package/dist/vault.js.map +1 -1
- package/package.json +1 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../src/adapters/slack/bot.ts"],"names":[],"mappings":"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","sourcesContent":["import { SocketModeClient } from \"@slack/socket-mode\";\nimport { WebClient } from \"@slack/web-api\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { readFile } from \"fs/promises\";\nimport { basename, join } from \"path\";\nimport type {\n Bot,\n BotAdapters,\n BotEvent,\n BotHandler,\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n ConversationKind,\n PlatformInfo,\n} from \"../../adapter.js\";\nimport type { EventsWatcher } from \"../../events.js\";\nimport * as log from \"../../log.js\";\nimport type { Attachment, ChannelStore } from \"../../store.js\";\nimport { PRODUCT_NAME, formatForceStopped, formatNothingRunning } from \"../../ui-copy.js\";\nimport {\n appendBotResponseLog,\n appendChannelLog,\n ChannelQueue,\n resolveOnlyScopedStopTarget,\n resolveStopTarget,\n withRetry,\n} from \"../shared.js\";\n\n// Slack WebClient errors carry either `code: \"rate_limited\"` (retry-after) or\n// the legacy `data.error === \"rate_limited\"` / 429 status shape.\nfunction slackIsRateLimited(err: Error): boolean {\n if ((err as { code?: unknown }).code === \"rate_limited\") return true;\n const data = (err as { data?: { error?: string; response?: { status?: number } } }).data;\n return data?.error === \"rate_limited\" || data?.response?.status === 429;\n}\n\nconst slackRetry = <T>(fn: () => Promise<T>): Promise<T> =>\n withRetry(fn, { isRateLimited: slackIsRateLimited });\nimport { createSlackAdapters } from \"./context.js\";\nimport { hasMaterializedSlackBranchSession } from \"./branch-manager.js\";\nimport { resolveSlackSessionKey } from \"./session.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SlackEvent {\n type: \"mention\" | \"dm\";\n conversationId: string;\n conversationKind: ConversationKind;\n channel: string;\n ts: string;\n thread_ts?: string;\n user: string;\n text: string;\n files?: Array<{ name?: string; url_private_download?: string; url_private?: string }>;\n /** Processed attachments with local paths (populated after logUserMessage) */\n attachments?: Attachment[];\n /** Session key passed through to BotEvent so handleEvent uses the correct persistent session */\n sessionKey?: string;\n}\n\nexport interface SlackUser {\n id: string;\n userName: string;\n displayName: string;\n}\n\nexport interface SlackChannel {\n id: string;\n name: string;\n}\n\n// Types used by agent.ts\nexport interface ChannelInfo {\n id: string;\n name: string;\n}\n\nexport interface UserInfo {\n id: string;\n userName: string;\n displayName: string;\n}\n\nexport interface SlackContext {\n message: {\n text: string;\n rawText: string;\n user: string;\n userName?: string;\n channel: string;\n ts: string;\n attachments: Array<{ localPath: string }>;\n };\n channelName?: string;\n channels: ChannelInfo[];\n users: UserInfo[];\n respond: (text: string, shouldLog?: boolean) => Promise<void>;\n replaceMessage: (text: string) => Promise<void>;\n respondDiagnostic: (text: string) => Promise<void>;\n setTyping: (isTyping: boolean) => Promise<void>;\n uploadFile: (filePath: string, title?: string) => Promise<void>;\n setWorking: (working: boolean) => Promise<void>;\n deleteMessage: () => Promise<void>;\n}\n\n// ============================================================================\n// SlackBot\n// ============================================================================\n\nexport class SlackBot implements Bot {\n private socketClient: SocketModeClient;\n private webClient: WebClient;\n private handler: BotHandler;\n private workingDir: string;\n private store: ChannelStore;\n private botUserId: string | null = null;\n private startupTs: string | null = null; // Messages older than this are just logged, not processed\n\n private users = new Map<string, SlackUser>();\n private channels = new Map<string, SlackChannel>();\n private queues = new Map<string, ChannelQueue>();\n private eventsWatcher: EventsWatcher | null = null;\n\n constructor(\n handler: BotHandler,\n config: { appToken: string; botToken: string; workingDir: string; store: ChannelStore },\n ) {\n this.handler = handler;\n this.workingDir = config.workingDir;\n this.store = config.store;\n this.socketClient = new SocketModeClient({ appToken: config.appToken });\n this.webClient = new WebClient(config.botToken);\n }\n\n setEventsWatcher(watcher: EventsWatcher): void {\n this.eventsWatcher = watcher;\n }\n\n // ==========================================================================\n // Public API\n // ==========================================================================\n\n async start(): Promise<void> {\n const auth = await this.webClient.auth.test();\n this.botUserId = auth.user_id as string;\n\n await Promise.all([this.fetchUsers(), this.fetchChannels()]);\n log.logInfo(`Loaded ${this.channels.size} channels, ${this.users.size} users`);\n\n await this.backfillAllChannels();\n\n this.setupEventHandlers();\n await this.socketClient.start();\n\n // Record startup time - messages older than this are just logged, not processed\n this.startupTs = (Date.now() / 1000).toFixed(6);\n\n log.logConnected();\n }\n\n getUser(userId: string): SlackUser | undefined {\n return this.users.get(userId);\n }\n\n getChannel(channelId: string): SlackChannel | undefined {\n return this.channels.get(channelId);\n }\n\n getAllUsers(): SlackUser[] {\n return Array.from(this.users.values());\n }\n\n getAllChannels(): SlackChannel[] {\n return Array.from(this.channels.values());\n }\n\n async postMessage(channel: string, text: string): Promise<string> {\n return slackRetry(async () => {\n const result = await this.webClient.chat.postMessage({ channel, text });\n return result.ts as string;\n });\n }\n\n async postEphemeral(channel: string, user: string, text: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.chat.postEphemeral({ channel, user, text });\n });\n }\n\n async openDirectMessage(userId: string): Promise<string> {\n return slackRetry(async () => {\n const result = await this.webClient.conversations.open({ users: userId });\n const channelId = result.channel?.id;\n if (!channelId) {\n throw new Error(`Failed to open DM for user ${userId}`);\n }\n return channelId;\n });\n }\n\n async updateMessage(channel: string, ts: string, text: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.chat.update({ channel, ts, text });\n });\n }\n\n async deleteMessage(channel: string, ts: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.chat.delete({ channel, ts });\n });\n }\n\n // ==========================================================================\n // Slack Assistant API (AI assistant experience)\n // ==========================================================================\n\n /** Set the status for an assistant thread (shows \"thinking\" state) */\n async setAssistantStatus(channel: string, threadTs: string, status: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.assistant.threads.setStatus({\n channel_id: channel,\n thread_ts: threadTs,\n status,\n });\n });\n }\n\n async postInThread(channel: string, threadTs: string, text: string): Promise<string> {\n return slackRetry(async () => {\n // Use Block Kit section for long messages to trigger Slack's \"Show more\" collapsing (~700 chars)\n const SECTION_TEXT_LIMIT = 3000;\n if (text.length > 500) {\n const blockText =\n text.length > SECTION_TEXT_LIMIT\n ? text.substring(0, SECTION_TEXT_LIMIT - 20) + \"\\n_(truncated)_\"\n : text;\n const result = await this.webClient.chat.postMessage({\n channel,\n thread_ts: threadTs,\n text, // full text as notification fallback\n blocks: [{ type: \"section\", text: { type: \"mrkdwn\", text: blockText } }],\n });\n return result.ts as string;\n }\n const result = await this.webClient.chat.postMessage({ channel, thread_ts: threadTs, text });\n return result.ts as string;\n });\n }\n\n async postInThreadBlocks(\n channel: string,\n threadTs: string,\n text: string,\n blocks: object[],\n ): Promise<string> {\n return slackRetry(async () => {\n const result = await this.webClient.chat.postMessage({\n channel,\n thread_ts: threadTs,\n text, // fallback for notifications\n blocks: blocks as any,\n });\n return result.ts as string;\n });\n }\n\n async uploadFile(\n channel: string,\n filePath: string,\n title?: string,\n threadTs?: string,\n ): Promise<void> {\n return slackRetry(async () => {\n const fileName = title || basename(filePath);\n const fileContent = readFileSync(filePath);\n await this.webClient.files.uploadV2({\n channel_id: channel,\n file: fileContent,\n filename: fileName,\n title: fileName,\n ...(threadTs ? { thread_ts: threadTs } : {}),\n } as Parameters<typeof this.webClient.files.uploadV2>[0]);\n });\n }\n\n logToFile(channel: string, entry: object): void {\n appendChannelLog(this.workingDir, channel, entry);\n }\n\n logBotResponse(channel: string, text: string, ts: string, threadTs?: string): void {\n appendBotResponseLog(this.workingDir, channel, text, ts, threadTs);\n }\n\n getPlatformInfo(): PlatformInfo {\n return {\n name: \"slack\",\n formattingGuide:\n \"## Slack Formatting (mrkdwn, NOT Markdown)\\nBold: *text*, Italic: _text_, Code: `code`, Block: ```code```, Links: <url|text>\\nDo NOT use **double asterisks** or [markdown](links).\",\n channels: this.getAllChannels().map((c) => ({ id: c.id, name: c.name })),\n users: this.getAllUsers().map((u) => ({\n id: u.id,\n userName: u.userName,\n displayName: u.displayName,\n })),\n diagnostics: {\n showUsageSummary: true,\n },\n };\n }\n\n // ==========================================================================\n // Events Integration\n // ==========================================================================\n\n /**\n * Enqueue an event for processing. Always queues (no \"already working\" rejection).\n * Returns true if enqueued, false if queue is full (max 5).\n */\n enqueueEvent(event: BotEvent): boolean {\n const conversationId = event.conversationId;\n const queue = this.getQueue(conversationId);\n if (queue.size() >= 5) {\n log.logWarning(\n `Event queue full for ${conversationId}, discarding: ${event.text.substring(0, 50)}`,\n );\n return false;\n }\n log.logInfo(`Enqueueing event for ${conversationId}: ${event.text.substring(0, 50)}`);\n queue.enqueue(() => {\n const slackEvent: SlackEvent = {\n type: event.type as SlackEvent[\"type\"],\n conversationId,\n conversationKind: event.conversationKind,\n channel: conversationId,\n ts: event.ts,\n thread_ts: event.thread_ts,\n user: event.user,\n text: event.text,\n attachments: event.attachments?.map((attachment) => ({\n original: attachment.name,\n localPath: attachment.localPath,\n })),\n sessionKey: event.sessionKey,\n };\n const adapters = createSlackAdapters(slackEvent, this, true);\n return this.handler.handleEvent(event, this, adapters, true);\n });\n return true;\n }\n\n // ==========================================================================\n // Private - Event Handlers\n // ==========================================================================\n\n private getQueue(channelId: string): ChannelQueue {\n let queue = this.queues.get(channelId);\n if (!queue) {\n queue = new ChannelQueue(\"Slack\");\n this.queues.set(channelId, queue);\n }\n return queue;\n }\n\n private resolveQueueKey(conversationId: string, sessionKey: string): string {\n if (!sessionKey.includes(\":\")) return sessionKey;\n\n return hasMaterializedSlackBranchSession(join(this.workingDir, conversationId), sessionKey)\n ? sessionKey\n : conversationId;\n }\n\n private shouldTriggerSharedThreadReply(channelId: string, threadTs?: string): boolean {\n if (!threadTs) return false;\n\n const sessionKey = resolveSlackSessionKey(channelId, threadTs);\n if (this.handler.isRunning(sessionKey)) return true;\n\n return hasMaterializedSlackBranchSession(join(this.workingDir, channelId), sessionKey);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildHomeView(): { type: \"home\"; blocks: any[] } {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const blocks: any[] = [\n {\n type: \"section\",\n text: {\n type: \"mrkdwn\",\n text: `*${PRODUCT_NAME}*\\nStart a new task or check on running work.`,\n },\n accessory: {\n type: \"image\",\n image_url: \"https://media1.tenor.com/m/lfDATg4Bhc0AAAAC/happy-cat.gif\",\n alt_text: PRODUCT_NAME,\n },\n },\n ];\n\n // --- Running tasks ---\n const runningSessions = this.handler.getRunningSessions();\n\n blocks.push(\n { type: \"divider\" },\n {\n type: \"header\",\n text: {\n type: \"plain_text\",\n text: `Running Tasks (${runningSessions.length})`,\n emoji: true,\n },\n },\n );\n\n if (runningSessions.length === 0) {\n blocks.push({\n type: \"context\",\n elements: [{ type: \"mrkdwn\", text: \"_No tasks running right now._\" }],\n });\n } else {\n // Threshold for \"stuck\" detection (10 minutes)\n const STUCK_THRESHOLD_MS = 10 * 60 * 1000;\n\n for (const session of runningSessions) {\n const channelId = session.sessionKey.split(\":\")[0];\n const channel = this.channels.get(channelId);\n const channelName = channel ? `#${channel.name}` : channelId;\n const elapsed = Math.floor((Date.now() - session.startedAt) / 60000);\n const elapsedStr = elapsed < 1 ? \"<1 min\" : `${elapsed} min`;\n\n // Check if task might be stuck\n const lastActivity = session.lastActivityAt ? Date.now() - session.lastActivityAt : 0;\n const isStuck = lastActivity > STUCK_THRESHOLD_MS;\n const statusText = isStuck ? \"_stuck_\" : \"_running_\";\n\n // Build status line: channel · status · time · step\n let statusLine = `${statusText} · ${elapsedStr}`;\n if (session.currentTool) {\n statusLine += ` · ${session.currentTool}`;\n }\n if (isStuck && lastActivity > 0) {\n const inactiveMin = Math.floor(lastActivity / 60000);\n statusLine += ` · idle ${inactiveMin}m`;\n }\n\n // Use context block for gray small text (like \"No scheduled jobs.\")\n blocks.push({\n type: \"context\",\n elements: [\n {\n type: \"mrkdwn\",\n text: `*${channelName}* · ${statusLine}`,\n },\n ],\n });\n\n // Add Force Stop button as separate element if stuck\n if (isStuck) {\n blocks.push({\n type: \"context\",\n elements: [\n {\n type: \"mrkdwn\",\n text: \" \",\n },\n {\n type: \"button\",\n text: { type: \"plain_text\", text: \"Force Stop\", emoji: true },\n action_id: `force_stop_${session.sessionKey.replace(/:/g, \"_\")}`,\n style: \"danger\",\n },\n ],\n });\n }\n }\n }\n\n // --- Cron jobs ---\n const periodicEvents = this.eventsWatcher?.getPeriodicEvents() ?? [];\n\n blocks.push(\n { type: \"divider\" },\n {\n type: \"header\",\n text: {\n type: \"plain_text\",\n text: `Scheduled Jobs (${periodicEvents.length})`,\n emoji: true,\n },\n },\n );\n\n if (periodicEvents.length === 0) {\n blocks.push({\n type: \"context\",\n elements: [{ type: \"mrkdwn\", text: \"_No scheduled jobs._\" }],\n });\n } else {\n for (const ev of periodicEvents) {\n const channelLabel =\n ev.platform === \"slack\"\n ? (() => {\n const channel = this.channels.get(ev.conversationId);\n const channelName = channel ? `#${channel.name}` : ev.conversationId;\n return `${ev.platform}:${channelName}`;\n })()\n : `${ev.platform}:${ev.conversationId}`;\n const nextStr = ev.nextRun\n ? new Date(ev.nextRun).toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n })\n : \"—\";\n blocks.push({\n type: \"section\",\n text: {\n type: \"mrkdwn\",\n text: `*${ev.text}*\\n└ \\`${ev.schedule}\\` · ${channelLabel} · Next: ${nextStr}`,\n },\n });\n }\n }\n\n // --- Footer ---\n blocks.push(\n { type: \"divider\" },\n {\n type: \"context\",\n elements: [\n { type: \"mrkdwn\", text: \"💡 @mention in a channel or send a DM to start a new task\" },\n ],\n },\n );\n\n return { type: \"home\", blocks };\n }\n\n private resolveStopTarget(channelId: string, threadTs?: string): string | null {\n const directTarget = resolveStopTarget({\n handler: this.handler,\n conversationId: channelId,\n sessionKey: threadTs ? resolveSlackSessionKey(channelId, threadTs) : undefined,\n });\n if (directTarget) return directTarget;\n if (threadTs) return null;\n return resolveOnlyScopedStopTarget(this.handler, channelId);\n }\n\n private createCommandAdapters(\n conversationId: string,\n userId: string,\n userName: string | undefined,\n text: string,\n ts: string,\n options: { ephemeralChannelId?: string } = {},\n ): BotAdapters {\n const message: ChatMessage = {\n id: ts,\n sessionKey: conversationId,\n conversationKind: options.ephemeralChannelId ? \"shared\" : \"direct\",\n userId,\n userName,\n text,\n attachments: [],\n };\n\n const respond = async (responseText: string) => {\n if (options.ephemeralChannelId) {\n await this.postEphemeral(options.ephemeralChannelId, userId, responseText);\n return;\n }\n const messageTs = await this.postMessage(conversationId, responseText);\n this.logBotResponse(conversationId, responseText, messageTs);\n };\n\n const responseCtx: ChatResponseContext = {\n respond,\n replaceResponse: respond,\n respondDiagnostic: respond,\n respondToolResult: async (result: ChatToolResult) => {\n const duration = (result.durationMs / 1000).toFixed(1);\n await respond(\n `${result.isError ? \"Error\" : \"Done\"} ${result.toolName} (${duration}s)\\n${result.result}`,\n );\n },\n setTyping: async () => {},\n setWorking: async () => {},\n uploadFile: async (filePath: string, title?: string) => {\n await this.uploadFile(conversationId, filePath, title);\n },\n deleteResponse: async () => {},\n };\n\n return {\n message,\n responseCtx,\n platform: this.getPlatformInfo(),\n };\n }\n\n private createSlashCommandBot(conversationId: string, threadTs?: string): Bot {\n return {\n start: async () => {},\n postMessage: async (_channel: string, text: string) => {\n if (threadTs) {\n return this.postInThread(conversationId, threadTs, text);\n }\n return this.postMessage(conversationId, text);\n },\n updateMessage: async (channel: string, ts: string, text: string) => {\n await this.updateMessage(channel, ts, text);\n },\n enqueueEvent: (event: BotEvent) => this.enqueueEvent(event),\n getPlatformInfo: () => this.getPlatformInfo(),\n };\n }\n\n private async routeSlashLoginCommand(payload: {\n command: string;\n text?: string;\n channel_id: string;\n user_id: string;\n user_name?: string;\n }): Promise<void> {\n const commandSuffix = payload.text?.trim();\n const commandText = commandSuffix ? `${payload.command} ${commandSuffix}` : payload.command;\n const createdAt = new Date();\n const eventTs = (createdAt.getTime() / 1000).toFixed(6);\n const sourceChannelId = payload.channel_id;\n const isDirectMessage = sourceChannelId.startsWith(\"D\");\n const targetChannelId = isDirectMessage\n ? sourceChannelId\n : await this.openDirectMessage(payload.user_id);\n const userName = payload.user_name ?? this.getUser(payload.user_id)?.userName;\n\n this.logToFile(targetChannelId, {\n date: createdAt.toISOString(),\n ts: eventTs,\n user: payload.user_id,\n userName,\n text: commandText,\n attachments: [],\n isBot: false,\n });\n\n if (!isDirectMessage) {\n await this.postEphemeral(\n sourceChannelId,\n payload.user_id,\n `我已私訊你 ${PRODUCT_NAME} 的登入連結,請到私訊完成設定。`,\n );\n }\n\n const event: BotEvent = {\n type: \"dm\",\n conversationId: targetChannelId,\n conversationKind: \"direct\",\n ts: eventTs,\n user: payload.user_id,\n text: commandText,\n attachments: [],\n sessionKey: targetChannelId,\n };\n\n const adapters = this.createCommandAdapters(\n targetChannelId,\n payload.user_id,\n userName,\n commandText,\n eventTs,\n );\n\n await this.handler.handleEvent(event, this, adapters, false);\n }\n\n private async routeSlashNewCommand(payload: {\n command: string;\n channel_id: string;\n user_id: string;\n user_name?: string;\n }): Promise<void> {\n const conversationId = payload.channel_id;\n if (!conversationId.startsWith(\"D\")) {\n await this.postEphemeral(\n conversationId,\n payload.user_id,\n `為了避免誤清除共享上下文,${payload.command} 目前只能在與 ${PRODUCT_NAME} 的私訊中使用。`,\n );\n return;\n }\n\n const createdAt = new Date();\n const eventTs = (createdAt.getTime() / 1000).toFixed(6);\n const userName = payload.user_name ?? this.getUser(payload.user_id)?.userName;\n\n this.logToFile(conversationId, {\n date: createdAt.toISOString(),\n ts: eventTs,\n user: payload.user_id,\n userName,\n text: payload.command,\n attachments: [],\n isBot: false,\n });\n\n const commandBot = this.createSlashCommandBot(conversationId);\n await this.handler.handleNew(conversationId, conversationId, commandBot);\n }\n\n private async routeSlashSessionCommand(payload: {\n command: string;\n channel_id: string;\n user_id: string;\n user_name?: string;\n }): Promise<void> {\n const conversationId = payload.channel_id;\n const isDirectMessage = conversationId.startsWith(\"D\");\n const createdAt = new Date();\n const eventTs = (createdAt.getTime() / 1000).toFixed(6);\n const userName = payload.user_name ?? this.getUser(payload.user_id)?.userName;\n const commandText = payload.command;\n\n this.logToFile(conversationId, {\n date: createdAt.toISOString(),\n ts: eventTs,\n user: payload.user_id,\n userName,\n text: commandText,\n attachments: [],\n isBot: false,\n });\n\n const sessionKey = conversationId;\n const event: BotEvent = {\n type: \"dm\",\n conversationId,\n conversationKind: isDirectMessage ? \"direct\" : \"shared\",\n ts: eventTs,\n user: payload.user_id,\n text: commandText,\n attachments: [],\n sessionKey,\n };\n\n const adapters = this.createCommandAdapters(\n conversationId,\n payload.user_id,\n userName,\n commandText,\n eventTs,\n isDirectMessage ? {} : { ephemeralChannelId: conversationId },\n );\n\n await this.handler.handleEvent(event, this, adapters, false);\n }\n\n private setupEventHandlers(): void {\n // Channel @mentions\n this.socketClient.on(\"app_mention\", ({ event, ack }) => {\n const e = event as {\n text: string;\n channel: string;\n user: string;\n ts: string;\n thread_ts?: string;\n files?: Array<{ name: string; url_private_download?: string; url_private?: string }>;\n };\n\n // Skip DMs (handled by message event)\n if (e.channel.startsWith(\"D\")) {\n ack();\n return;\n }\n\n // Top-level mentions use a persistent channel session.\n // Thread replies get their own isolated session (channelId:thread_ts).\n const sessionKey = resolveSlackSessionKey(e.channel, e.thread_ts);\n\n const slackEvent: SlackEvent = {\n type: \"mention\",\n conversationId: e.channel,\n conversationKind: \"shared\",\n channel: e.channel,\n ts: e.ts,\n thread_ts: e.thread_ts,\n user: e.user,\n text: e.text.replace(/<@[A-Z0-9]+>/gi, \"\").trim(),\n files: e.files,\n sessionKey,\n };\n\n const attachmentsPromise = this.logUserMessage(slackEvent);\n\n // Only trigger processing for messages AFTER startup (not replayed old messages)\n if (this.startupTs && e.ts < this.startupTs) {\n log.logInfo(\n `[${e.channel}] Logged old message (pre-startup), not triggering: ${slackEvent.text.substring(0, 30)}`,\n );\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n // Check for stop command - execute immediately, don't queue!\n if (slackEvent.text.toLowerCase().trim() === \"stop\") {\n const stopTarget = this.resolveStopTarget(e.channel, e.thread_ts);\n if (stopTarget) {\n this.handler.handleStop(stopTarget, e.channel, this);\n } else {\n this.postMessage(e.channel, formatNothingRunning(\"slack\"));\n }\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n this.getQueue(this.resolveQueueKey(e.channel, sessionKey)).enqueue(async () => {\n slackEvent.attachments = await attachmentsPromise;\n const adapters = createSlackAdapters(slackEvent, this, false);\n return this.handler.handleEvent(\n slackEvent as unknown as import(\"../../adapter.js\").BotEvent,\n this,\n adapters,\n false,\n );\n });\n\n ack();\n });\n\n // All messages (for logging) + DMs (for triggering)\n this.socketClient.on(\"message\", ({ event, ack }) => {\n const e = event as {\n text?: string;\n channel: string;\n user?: string;\n ts: string;\n thread_ts?: string;\n channel_type?: string;\n subtype?: string;\n bot_id?: string;\n files?: Array<{ name: string; url_private_download?: string; url_private?: string }>;\n };\n\n // Skip bot messages, edits, etc.\n if (e.bot_id || !e.user || e.user === this.botUserId) {\n ack();\n return;\n }\n if (e.subtype !== undefined && e.subtype !== \"file_share\") {\n ack();\n return;\n }\n if (!e.text && (!e.files || e.files.length === 0)) {\n ack();\n return;\n }\n\n const isDM = e.channel_type === \"im\";\n const conversationKind: ConversationKind = isDM ? \"direct\" : \"shared\";\n const isBotMention = e.text?.includes(`<@${this.botUserId}>`);\n\n // Skip channel @mentions - already handled by app_mention event\n if (!isDM && isBotMention) {\n ack();\n return;\n }\n\n const isSharedThreadReply =\n !isDM && this.shouldTriggerSharedThreadReply(e.channel, e.thread_ts);\n const sessionKey =\n isDM || isSharedThreadReply ? resolveSlackSessionKey(e.channel, e.thread_ts) : undefined;\n\n const slackEvent: SlackEvent = {\n type: isDM ? \"dm\" : \"mention\",\n conversationId: e.channel,\n conversationKind,\n channel: e.channel,\n ts: e.ts,\n thread_ts: e.thread_ts,\n user: e.user,\n text: (e.text || \"\").replace(/<@[A-Z0-9]+>/gi, \"\").trim(),\n files: e.files,\n sessionKey,\n };\n\n const attachmentsPromise = this.logUserMessage(slackEvent);\n\n // Only trigger processing for messages AFTER startup (not replayed old messages)\n if (this.startupTs && e.ts < this.startupTs) {\n log.logInfo(\n `[${e.channel}] Skipping old message (pre-startup): ${slackEvent.text.substring(0, 30)}`,\n );\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n // Check for stop command in channel threads (without @mention)\n // app_mention handles \"@mama stop\", but bare \"stop\" in a thread comes here\n if (!isDM && e.thread_ts && slackEvent.text.toLowerCase().trim() === \"stop\") {\n const stopTarget = this.resolveStopTarget(e.channel, e.thread_ts);\n if (stopTarget) {\n this.handler.handleStop(stopTarget, e.channel, this);\n } else {\n this.postMessage(e.channel, formatNothingRunning(\"slack\"));\n }\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n // Trigger handler for DMs and bare replies inside shared-channel threads.\n if (isDM || isSharedThreadReply) {\n const activeSessionKey =\n slackEvent.sessionKey ?? resolveSlackSessionKey(e.channel, e.thread_ts);\n // Check for stop command - execute immediately, don't queue!\n if (slackEvent.text.toLowerCase().trim() === \"stop\") {\n const stopTarget = this.resolveStopTarget(e.channel, e.thread_ts);\n if (stopTarget) {\n this.handler.handleStop(stopTarget, e.channel, this); // Don't await, don't queue\n } else {\n this.postMessage(e.channel, formatNothingRunning(\"slack\"));\n }\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n this.getQueue(this.resolveQueueKey(e.channel, activeSessionKey)).enqueue(async () => {\n slackEvent.attachments = await attachmentsPromise;\n const adapters = createSlackAdapters(slackEvent, this, false);\n return this.handler.handleEvent(\n slackEvent as unknown as import(\"../../adapter.js\").BotEvent,\n this,\n adapters,\n false,\n );\n });\n } else {\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n }\n\n ack();\n });\n\n this.socketClient.on(\"slash_commands\", async ({ body, ack }) => {\n const payload = body as {\n command?: string;\n text?: string;\n channel_id?: string;\n user_id?: string;\n user_name?: string;\n };\n\n await ack();\n\n if (!payload.command || !payload.channel_id || !payload.user_id) {\n return;\n }\n\n const handlerPromise =\n payload.command === \"/pi-login\"\n ? this.routeSlashLoginCommand({\n command: payload.command,\n text: payload.text,\n channel_id: payload.channel_id,\n user_id: payload.user_id,\n user_name: payload.user_name,\n })\n : payload.command === \"/pi-new\"\n ? this.routeSlashNewCommand({\n command: payload.command,\n channel_id: payload.channel_id,\n user_id: payload.user_id,\n user_name: payload.user_name,\n })\n : payload.command === \"/pi-session\"\n ? this.routeSlashSessionCommand({\n command: payload.command,\n channel_id: payload.channel_id,\n user_id: payload.user_id,\n user_name: payload.user_name,\n })\n : null;\n\n if (!handlerPromise) {\n return;\n }\n\n handlerPromise.catch((err) => {\n log.logWarning(\n \"Slack slash command error\",\n err instanceof Error ? err.message : String(err),\n );\n });\n });\n\n // App Home tab\n this.socketClient.on(\"app_home_opened\", ({ event, ack }) => {\n const e = event as { user: string; tab: string };\n ack();\n if (e.tab !== \"home\") return;\n\n this.webClient.views\n .publish({\n user_id: e.user,\n view: this.buildHomeView(),\n })\n .catch((err) => {\n log.logWarning(`Failed to publish App Home view`, String(err));\n });\n });\n\n // Handle button clicks (Force Stop)\n this.socketClient.on(\"block_actions\", async ({ body, ack }) => {\n const action = body.actions?.[0];\n if (!action || !action.action_id?.startsWith(\"force_stop_\")) {\n ack();\n return;\n }\n\n ack();\n const sessionKey = action.action_id.replace(\"force_stop_\", \"\").replace(/_/g, \":\");\n const userId = body.user?.id;\n const channelId = body.container?.channel_id || sessionKey.split(\":\")[0];\n\n log.logInfo(`[Force Stop] User ${userId} requested force stop for ${sessionKey}`);\n\n // Use handler's forceStop method\n this.handler.forceStop(sessionKey);\n\n // Notify in channel\n await this.postMessage(channelId, formatForceStopped(\"slack\", userId ?? \"unknown\"));\n\n // Refresh home tab\n if (userId) {\n this.webClient.views\n .publish({\n user_id: userId,\n view: this.buildHomeView(),\n })\n .catch((err) => {\n log.logWarning(`Failed to refresh App Home view`, String(err));\n });\n }\n });\n }\n\n /**\n * Log a user message to log.jsonl after attachments are ready.\n */\n private async logUserMessage(event: SlackEvent): Promise<Attachment[]> {\n const user = this.users.get(event.user);\n const attachments = event.files\n ? await this.store.processAttachments(event.channel, event.files, event.ts)\n : [];\n this.logToFile(event.channel, {\n date: new Date(parseFloat(event.ts) * 1000).toISOString(),\n ts: event.ts,\n threadTs: event.thread_ts,\n user: event.user,\n userName: user?.userName,\n displayName: user?.displayName,\n text: event.text,\n attachments,\n isBot: false,\n });\n return attachments;\n }\n\n // ==========================================================================\n // Private - Backfill\n // ==========================================================================\n\n private async getExistingTimestamps(channelId: string): Promise<Set<string>> {\n const logPath = join(this.workingDir, channelId, \"log.jsonl\");\n const timestamps = new Set<string>();\n if (!existsSync(logPath)) return timestamps;\n\n const content = await readFile(logPath, \"utf-8\");\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n for (const line of lines) {\n try {\n const entry = JSON.parse(line);\n if (entry.ts) timestamps.add(entry.ts);\n } catch {}\n }\n return timestamps;\n }\n\n private async backfillChannel(channelId: string): Promise<number> {\n const existingTs = await this.getExistingTimestamps(channelId);\n\n // Find the biggest ts in log.jsonl\n let latestTs: string | undefined;\n for (const ts of existingTs) {\n if (!latestTs || parseFloat(ts) > parseFloat(latestTs)) latestTs = ts;\n }\n\n type Message = {\n user?: string;\n bot_id?: string;\n text?: string;\n ts?: string;\n thread_ts?: string;\n subtype?: string;\n files?: Array<{ name: string }>;\n };\n const allMessages: Message[] = [];\n\n let cursor: string | undefined;\n let pageCount = 0;\n const maxPages = 3;\n\n do {\n const result = await this.webClient.conversations.history({\n channel: channelId,\n oldest: latestTs, // Only fetch messages newer than what we have\n inclusive: false,\n limit: 1000,\n cursor,\n });\n if (result.messages) {\n allMessages.push(...(result.messages as Message[]));\n }\n cursor = result.response_metadata?.next_cursor;\n pageCount++;\n } while (cursor && pageCount < maxPages);\n\n // Filter: include mama's messages, exclude other bots, skip already logged\n const relevantMessages = allMessages.filter((msg) => {\n if (!msg.ts || existingTs.has(msg.ts)) return false; // Skip duplicates\n if (msg.user === this.botUserId) return true;\n if (msg.bot_id) return false;\n if (msg.subtype !== undefined && msg.subtype !== \"file_share\") return false;\n if (!msg.user) return false;\n if (!msg.text && (!msg.files || msg.files.length === 0)) return false;\n return true;\n });\n\n // Reverse to chronological order\n relevantMessages.reverse();\n\n // Log each message to log.jsonl\n for (const msg of relevantMessages) {\n const isMamaMessage = msg.user === this.botUserId;\n const user = this.users.get(msg.user!);\n // Strip @mentions from text (same as live messages)\n const text = (msg.text || \"\").replace(/<@[A-Z0-9]+>/gi, \"\").trim();\n const attachments = msg.files\n ? await this.store.processAttachments(channelId, msg.files, msg.ts!)\n : [];\n\n this.logToFile(channelId, {\n date: new Date(parseFloat(msg.ts!) * 1000).toISOString(),\n ts: msg.ts!,\n threadTs: msg.thread_ts,\n user: isMamaMessage ? \"bot\" : msg.user!,\n userName: isMamaMessage ? undefined : user?.userName,\n displayName: isMamaMessage ? undefined : user?.displayName,\n text,\n attachments,\n isBot: isMamaMessage,\n });\n }\n\n return relevantMessages.length;\n }\n\n private async backfillAllChannels(): Promise<void> {\n const startTime = Date.now();\n\n // Only backfill channels that already have a log.jsonl (mama has interacted with them before)\n const channelsToBackfill: Array<[string, SlackChannel]> = [];\n for (const [channelId, channel] of this.channels) {\n const logPath = join(this.workingDir, channelId, \"log.jsonl\");\n if (existsSync(logPath)) {\n channelsToBackfill.push([channelId, channel]);\n }\n }\n\n log.logBackfillStart(channelsToBackfill.length);\n\n let totalMessages = 0;\n for (const [channelId, channel] of channelsToBackfill) {\n try {\n const count = await this.backfillChannel(channelId);\n if (count > 0) log.logBackfillChannel(channel.name, count);\n totalMessages += count;\n } catch (error) {\n log.logWarning(`Failed to backfill #${channel.name}`, String(error));\n }\n\n // Add delay between channels to avoid hitting Slack rate limits\n if (channelId !== channelsToBackfill[channelsToBackfill.length - 1][0]) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n }\n\n const durationMs = Date.now() - startTime;\n log.logBackfillComplete(totalMessages, durationMs);\n }\n\n // ==========================================================================\n // Private - Fetch Users/Channels\n // ==========================================================================\n\n private async fetchUsers(): Promise<void> {\n let cursor: string | undefined;\n do {\n const result = await this.webClient.users.list({ limit: 200, cursor });\n const members = result.members as\n | Array<{ id?: string; name?: string; real_name?: string; deleted?: boolean }>\n | undefined;\n if (members) {\n for (const u of members) {\n if (u.id && u.name && !u.deleted) {\n this.users.set(u.id, {\n id: u.id,\n userName: u.name,\n displayName: u.real_name || u.name,\n });\n }\n }\n }\n cursor = result.response_metadata?.next_cursor;\n } while (cursor);\n }\n\n private async fetchChannels(): Promise<void> {\n // Fetch public/private channels\n let cursor: string | undefined;\n do {\n const result = await this.webClient.conversations.list({\n types: \"public_channel,private_channel\",\n exclude_archived: true,\n limit: 200,\n cursor,\n });\n const channels = result.channels as\n | Array<{ id?: string; name?: string; is_member?: boolean }>\n | undefined;\n if (channels) {\n for (const c of channels) {\n if (c.id && c.name && c.is_member) {\n this.channels.set(c.id, { id: c.id, name: c.name });\n }\n }\n }\n cursor = result.response_metadata?.next_cursor;\n } while (cursor);\n\n // Also fetch DM channels (IMs)\n cursor = undefined;\n do {\n const result = await this.webClient.conversations.list({\n types: \"im\",\n limit: 200,\n cursor,\n });\n const ims = result.channels as Array<{ id?: string; user?: string }> | undefined;\n if (ims) {\n for (const im of ims) {\n if (im.id) {\n // Use user's name as channel name for DMs\n const user = im.user ? this.users.get(im.user) : undefined;\n const name = user ? `DM:${user.userName}` : `DM:${im.id}`;\n this.channels.set(im.id, { id: im.id, name });\n }\n }\n }\n cursor = result.response_metadata?.next_cursor;\n } while (cursor);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../src/adapters/slack/bot.ts"],"names":[],"mappings":"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","sourcesContent":["import { SocketModeClient } from \"@slack/socket-mode\";\nimport { WebClient } from \"@slack/web-api\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { readFile } from \"fs/promises\";\nimport { basename, join } from \"path\";\nimport type {\n Bot,\n BotAdapters,\n BotEvent,\n BotHandler,\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n ConversationKind,\n PlatformInfo,\n} from \"../../adapter.js\";\nimport type { EventsWatcher } from \"../../events.js\";\nimport * as log from \"../../log.js\";\nimport type { Attachment, ChannelStore } from \"../../store.js\";\nimport { PRODUCT_NAME, formatForceStopped, formatNothingRunning } from \"../../ui-copy.js\";\nimport {\n appendBotResponseLog,\n appendChannelLog,\n ChannelQueue,\n resolveOnlyScopedStopTarget,\n resolveStopTarget,\n withRetry,\n} from \"../shared.js\";\n\n// Slack WebClient errors carry either `code: \"rate_limited\"` (retry-after) or\n// the legacy `data.error === \"rate_limited\"` / 429 status shape.\nfunction slackIsRateLimited(err: Error): boolean {\n if ((err as { code?: unknown }).code === \"rate_limited\") return true;\n const data = (err as { data?: { error?: string; response?: { status?: number } } }).data;\n return data?.error === \"rate_limited\" || data?.response?.status === 429;\n}\n\nconst slackRetry = <T>(fn: () => Promise<T>): Promise<T> =>\n withRetry(fn, { isRateLimited: slackIsRateLimited });\nimport { createSlackAdapters } from \"./context.js\";\nimport { hasMaterializedSlackBranchSession } from \"./branch-manager.js\";\nimport { resolveSlackSessionKey } from \"./session.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SlackEvent {\n type: \"mention\" | \"dm\";\n conversationId: string;\n conversationKind: ConversationKind;\n channel: string;\n ts: string;\n thread_ts?: string;\n user: string;\n text: string;\n files?: Array<{ name?: string; url_private_download?: string; url_private?: string }>;\n /** Processed attachments with local paths (populated after logUserMessage) */\n attachments?: Attachment[];\n /** Session key passed through to BotEvent so handleEvent uses the correct persistent session */\n sessionKey?: string;\n}\n\nexport interface SlackUser {\n id: string;\n userName: string;\n displayName: string;\n}\n\nexport interface SlackChannel {\n id: string;\n name: string;\n}\n\n// Types used by agent.ts\nexport interface ChannelInfo {\n id: string;\n name: string;\n}\n\nexport interface UserInfo {\n id: string;\n userName: string;\n displayName: string;\n}\n\nexport interface SlackContext {\n message: {\n text: string;\n rawText: string;\n user: string;\n userName?: string;\n channel: string;\n ts: string;\n attachments: Array<{ localPath: string }>;\n };\n channelName?: string;\n channels: ChannelInfo[];\n users: UserInfo[];\n respond: (text: string, shouldLog?: boolean) => Promise<void>;\n replaceMessage: (text: string) => Promise<void>;\n respondDiagnostic: (text: string) => Promise<void>;\n setTyping: (isTyping: boolean) => Promise<void>;\n uploadFile: (filePath: string, title?: string) => Promise<void>;\n setWorking: (working: boolean) => Promise<void>;\n deleteMessage: () => Promise<void>;\n}\n\n// ============================================================================\n// SlackBot\n// ============================================================================\n\nexport class SlackBot implements Bot {\n private socketClient: SocketModeClient;\n private webClient: WebClient;\n private handler: BotHandler;\n private workingDir: string;\n private store: ChannelStore;\n private botUserId: string | null = null;\n private startupTs: string | null = null; // Messages older than this are just logged, not processed\n\n private users = new Map<string, SlackUser>();\n private channels = new Map<string, SlackChannel>();\n private queues = new Map<string, ChannelQueue>();\n private eventsWatcher: EventsWatcher | null = null;\n\n constructor(\n handler: BotHandler,\n config: { appToken: string; botToken: string; workingDir: string; store: ChannelStore },\n ) {\n this.handler = handler;\n this.workingDir = config.workingDir;\n this.store = config.store;\n this.socketClient = new SocketModeClient({ appToken: config.appToken });\n this.webClient = new WebClient(config.botToken);\n }\n\n setEventsWatcher(watcher: EventsWatcher): void {\n this.eventsWatcher = watcher;\n }\n\n // ==========================================================================\n // Public API\n // ==========================================================================\n\n async start(): Promise<void> {\n const auth = await this.webClient.auth.test();\n this.botUserId = auth.user_id as string;\n\n await Promise.all([this.fetchUsers(), this.fetchChannels()]);\n log.logInfo(`Loaded ${this.channels.size} channels, ${this.users.size} users`);\n\n await this.backfillAllChannels();\n\n this.setupEventHandlers();\n await this.socketClient.start();\n\n // Record startup time - messages older than this are just logged, not processed\n this.startupTs = (Date.now() / 1000).toFixed(6);\n\n log.logConnected();\n }\n\n getUser(userId: string): SlackUser | undefined {\n return this.users.get(userId);\n }\n\n getChannel(channelId: string): SlackChannel | undefined {\n return this.channels.get(channelId);\n }\n\n getAllUsers(): SlackUser[] {\n return Array.from(this.users.values());\n }\n\n getAllChannels(): SlackChannel[] {\n return Array.from(this.channels.values());\n }\n\n async postMessage(channel: string, text: string): Promise<string> {\n return slackRetry(async () => {\n const result = await this.webClient.chat.postMessage({ channel, text });\n return result.ts as string;\n });\n }\n\n async postEphemeral(channel: string, user: string, text: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.chat.postEphemeral({ channel, user, text });\n });\n }\n\n async postPrivate(conversationId: string, userId: string, text: string): Promise<void> {\n await this.postEphemeral(conversationId, userId, text);\n }\n\n async openDirectMessage(userId: string): Promise<string> {\n return slackRetry(async () => {\n const result = await this.webClient.conversations.open({ users: userId });\n const channelId = result.channel?.id;\n if (!channelId) {\n throw new Error(`Failed to open DM for user ${userId}`);\n }\n return channelId;\n });\n }\n\n async updateMessage(channel: string, ts: string, text: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.chat.update({ channel, ts, text });\n });\n }\n\n async deleteMessage(channel: string, ts: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.chat.delete({ channel, ts });\n });\n }\n\n // ==========================================================================\n // Slack Assistant API (AI assistant experience)\n // ==========================================================================\n\n /** Set the status for an assistant thread (shows \"thinking\" state) */\n async setAssistantStatus(channel: string, threadTs: string, status: string): Promise<void> {\n return slackRetry(async () => {\n await this.webClient.assistant.threads.setStatus({\n channel_id: channel,\n thread_ts: threadTs,\n status,\n });\n });\n }\n\n async postInThread(channel: string, threadTs: string, text: string): Promise<string> {\n return slackRetry(async () => {\n // Use Block Kit section for long messages to trigger Slack's \"Show more\" collapsing (~700 chars)\n const SECTION_TEXT_LIMIT = 3000;\n if (text.length > 500) {\n const blockText =\n text.length > SECTION_TEXT_LIMIT\n ? text.substring(0, SECTION_TEXT_LIMIT - 20) + \"\\n_(truncated)_\"\n : text;\n const result = await this.webClient.chat.postMessage({\n channel,\n thread_ts: threadTs,\n text, // full text as notification fallback\n blocks: [{ type: \"section\", text: { type: \"mrkdwn\", text: blockText } }],\n });\n return result.ts as string;\n }\n const result = await this.webClient.chat.postMessage({ channel, thread_ts: threadTs, text });\n return result.ts as string;\n });\n }\n\n async postInThreadBlocks(\n channel: string,\n threadTs: string,\n text: string,\n blocks: object[],\n ): Promise<string> {\n return slackRetry(async () => {\n const result = await this.webClient.chat.postMessage({\n channel,\n thread_ts: threadTs,\n text, // fallback for notifications\n blocks: blocks as any,\n });\n return result.ts as string;\n });\n }\n\n async uploadFile(\n channel: string,\n filePath: string,\n title?: string,\n threadTs?: string,\n ): Promise<void> {\n return slackRetry(async () => {\n const fileName = title || basename(filePath);\n const fileContent = readFileSync(filePath);\n await this.webClient.files.uploadV2({\n channel_id: channel,\n file: fileContent,\n filename: fileName,\n title: fileName,\n ...(threadTs ? { thread_ts: threadTs } : {}),\n } as Parameters<typeof this.webClient.files.uploadV2>[0]);\n });\n }\n\n logToFile(channel: string, entry: object): void {\n appendChannelLog(this.workingDir, channel, entry);\n }\n\n logBotResponse(channel: string, text: string, ts: string, threadTs?: string): void {\n appendBotResponseLog(this.workingDir, channel, text, ts, threadTs);\n }\n\n getPlatformInfo(): PlatformInfo {\n return {\n name: \"slack\",\n formattingGuide:\n \"## Slack Formatting (mrkdwn, NOT Markdown)\\nBold: *text*, Italic: _text_, Code: `code`, Block: ```code```, Links: <url|text>\\nDo NOT use **double asterisks** or [markdown](links).\",\n channels: this.getAllChannels().map((c) => ({ id: c.id, name: c.name })),\n users: this.getAllUsers().map((u) => ({\n id: u.id,\n userName: u.userName,\n displayName: u.displayName,\n })),\n diagnostics: {\n showUsageSummary: true,\n },\n };\n }\n\n // ==========================================================================\n // Events Integration\n // ==========================================================================\n\n /**\n * Enqueue an event for processing. Always queues (no \"already working\" rejection).\n * Returns true if enqueued, false if queue is full (max 5).\n */\n enqueueEvent(event: BotEvent): boolean {\n const conversationId = event.conversationId;\n const queue = this.getQueue(conversationId);\n if (queue.size() >= 5) {\n log.logWarning(\n `Event queue full for ${conversationId}, discarding: ${event.text.substring(0, 50)}`,\n );\n return false;\n }\n log.logInfo(`Enqueueing event for ${conversationId}: ${event.text.substring(0, 50)}`);\n queue.enqueue(() => {\n const slackEvent: SlackEvent = {\n type: event.type as SlackEvent[\"type\"],\n conversationId,\n conversationKind: event.conversationKind,\n channel: conversationId,\n ts: event.ts,\n thread_ts: event.thread_ts,\n user: event.user,\n text: event.text,\n attachments: event.attachments?.map((attachment) => ({\n original: attachment.name,\n localPath: attachment.localPath,\n })),\n sessionKey: event.sessionKey,\n };\n const adapters = createSlackAdapters(slackEvent, this, true);\n return this.handler.handleEvent(event, this, adapters, true);\n });\n return true;\n }\n\n // ==========================================================================\n // Private - Event Handlers\n // ==========================================================================\n\n private getQueue(channelId: string): ChannelQueue {\n let queue = this.queues.get(channelId);\n if (!queue) {\n queue = new ChannelQueue(\"Slack\");\n this.queues.set(channelId, queue);\n }\n return queue;\n }\n\n private resolveQueueKey(conversationId: string, sessionKey: string): string {\n if (!sessionKey.includes(\":\")) return sessionKey;\n\n return hasMaterializedSlackBranchSession(join(this.workingDir, conversationId), sessionKey)\n ? sessionKey\n : conversationId;\n }\n\n private shouldTriggerSharedThreadReply(channelId: string, threadTs?: string): boolean {\n if (!threadTs) return false;\n\n const sessionKey = resolveSlackSessionKey(channelId, threadTs);\n if (this.handler.isRunning(sessionKey)) return true;\n\n return hasMaterializedSlackBranchSession(join(this.workingDir, channelId), sessionKey);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildHomeView(): { type: \"home\"; blocks: any[] } {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const blocks: any[] = [\n {\n type: \"section\",\n text: {\n type: \"mrkdwn\",\n text: `*${PRODUCT_NAME}*\\nStart a new task or check on running work.`,\n },\n accessory: {\n type: \"image\",\n image_url: \"https://media1.tenor.com/m/lfDATg4Bhc0AAAAC/happy-cat.gif\",\n alt_text: PRODUCT_NAME,\n },\n },\n ];\n\n // --- Running tasks ---\n const runningSessions = this.handler.getRunningSessions();\n\n blocks.push(\n { type: \"divider\" },\n {\n type: \"header\",\n text: {\n type: \"plain_text\",\n text: `Running Tasks (${runningSessions.length})`,\n emoji: true,\n },\n },\n );\n\n if (runningSessions.length === 0) {\n blocks.push({\n type: \"context\",\n elements: [{ type: \"mrkdwn\", text: \"_No tasks running right now._\" }],\n });\n } else {\n // Threshold for \"stuck\" detection (10 minutes)\n const STUCK_THRESHOLD_MS = 10 * 60 * 1000;\n\n for (const session of runningSessions) {\n const channelId = session.sessionKey.split(\":\")[0];\n const channel = this.channels.get(channelId);\n const channelName = channel ? `#${channel.name}` : channelId;\n const elapsed = Math.floor((Date.now() - session.startedAt) / 60000);\n const elapsedStr = elapsed < 1 ? \"<1 min\" : `${elapsed} min`;\n\n // Check if task might be stuck\n const lastActivity = session.lastActivityAt ? Date.now() - session.lastActivityAt : 0;\n const isStuck = lastActivity > STUCK_THRESHOLD_MS;\n const statusText = isStuck ? \"_stuck_\" : \"_running_\";\n\n // Build status line: channel · status · time · step\n let statusLine = `${statusText} · ${elapsedStr}`;\n if (session.currentTool) {\n statusLine += ` · ${session.currentTool}`;\n }\n if (isStuck && lastActivity > 0) {\n const inactiveMin = Math.floor(lastActivity / 60000);\n statusLine += ` · idle ${inactiveMin}m`;\n }\n\n // Use context block for gray small text (like \"No scheduled jobs.\")\n blocks.push({\n type: \"context\",\n elements: [\n {\n type: \"mrkdwn\",\n text: `*${channelName}* · ${statusLine}`,\n },\n ],\n });\n\n // Add Force Stop button as separate element if stuck\n if (isStuck) {\n blocks.push({\n type: \"context\",\n elements: [\n {\n type: \"mrkdwn\",\n text: \" \",\n },\n {\n type: \"button\",\n text: { type: \"plain_text\", text: \"Force Stop\", emoji: true },\n action_id: `force_stop_${session.sessionKey.replace(/:/g, \"_\")}`,\n style: \"danger\",\n },\n ],\n });\n }\n }\n }\n\n // --- Cron jobs ---\n const periodicEvents = this.eventsWatcher?.getPeriodicEvents() ?? [];\n\n blocks.push(\n { type: \"divider\" },\n {\n type: \"header\",\n text: {\n type: \"plain_text\",\n text: `Scheduled Jobs (${periodicEvents.length})`,\n emoji: true,\n },\n },\n );\n\n if (periodicEvents.length === 0) {\n blocks.push({\n type: \"context\",\n elements: [{ type: \"mrkdwn\", text: \"_No scheduled jobs._\" }],\n });\n } else {\n for (const ev of periodicEvents) {\n const channelLabel =\n ev.platform === \"slack\"\n ? (() => {\n const channel = this.channels.get(ev.conversationId);\n const channelName = channel ? `#${channel.name}` : ev.conversationId;\n return `${ev.platform}:${channelName}`;\n })()\n : `${ev.platform}:${ev.conversationId}`;\n const nextStr = ev.nextRun\n ? new Date(ev.nextRun).toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n })\n : \"—\";\n blocks.push({\n type: \"section\",\n text: {\n type: \"mrkdwn\",\n text: `*${ev.text}*\\n└ \\`${ev.schedule}\\` · ${channelLabel} · Next: ${nextStr}`,\n },\n });\n }\n }\n\n // --- Footer ---\n blocks.push(\n { type: \"divider\" },\n {\n type: \"context\",\n elements: [\n { type: \"mrkdwn\", text: \"💡 @mention in a channel or send a DM to start a new task\" },\n ],\n },\n );\n\n return { type: \"home\", blocks };\n }\n\n private resolveStopTarget(channelId: string, threadTs?: string): string | null {\n const directTarget = resolveStopTarget({\n handler: this.handler,\n conversationId: channelId,\n sessionKey: threadTs ? resolveSlackSessionKey(channelId, threadTs) : undefined,\n });\n if (directTarget) return directTarget;\n if (threadTs) return null;\n return resolveOnlyScopedStopTarget(this.handler, channelId);\n }\n\n private createCommandAdapters(\n conversationId: string,\n userId: string,\n userName: string | undefined,\n text: string,\n ts: string,\n options: { ephemeralChannelId?: string } = {},\n ): BotAdapters {\n const message: ChatMessage = {\n id: ts,\n sessionKey: conversationId,\n conversationKind: options.ephemeralChannelId ? \"shared\" : \"direct\",\n userId,\n userName,\n text,\n attachments: [],\n };\n\n const respond = async (responseText: string) => {\n if (options.ephemeralChannelId) {\n await this.postEphemeral(options.ephemeralChannelId, userId, responseText);\n return;\n }\n const messageTs = await this.postMessage(conversationId, responseText);\n this.logBotResponse(conversationId, responseText, messageTs);\n };\n\n const responseCtx: ChatResponseContext = {\n respond,\n replaceResponse: respond,\n respondDiagnostic: respond,\n respondToolResult: async (result: ChatToolResult) => {\n const duration = (result.durationMs / 1000).toFixed(1);\n await respond(\n `${result.isError ? \"Error\" : \"Done\"} ${result.toolName} (${duration}s)\\n${result.result}`,\n );\n },\n setTyping: async () => {},\n setWorking: async () => {},\n uploadFile: async (filePath: string, title?: string) => {\n await this.uploadFile(conversationId, filePath, title);\n },\n deleteResponse: async () => {},\n };\n\n return {\n message,\n responseCtx,\n platform: this.getPlatformInfo(),\n };\n }\n\n private createSlashCommandBot(conversationId: string, threadTs?: string): Bot {\n return {\n start: async () => {},\n postMessage: async (_channel: string, text: string) => {\n if (threadTs) {\n return this.postInThread(conversationId, threadTs, text);\n }\n return this.postMessage(conversationId, text);\n },\n updateMessage: async (channel: string, ts: string, text: string) => {\n await this.updateMessage(channel, ts, text);\n },\n enqueueEvent: (event: BotEvent) => this.enqueueEvent(event),\n getPlatformInfo: () => this.getPlatformInfo(),\n };\n }\n\n private async routeSlashLoginCommand(payload: {\n command: string;\n text?: string;\n channel_id: string;\n user_id: string;\n user_name?: string;\n }): Promise<void> {\n const commandSuffix = payload.text?.trim();\n const commandText = commandSuffix ? `${payload.command} ${commandSuffix}` : payload.command;\n const createdAt = new Date();\n const eventTs = (createdAt.getTime() / 1000).toFixed(6);\n const sourceChannelId = payload.channel_id;\n const isDirectMessage = sourceChannelId.startsWith(\"D\");\n const targetChannelId = isDirectMessage\n ? sourceChannelId\n : await this.openDirectMessage(payload.user_id);\n const userName = payload.user_name ?? this.getUser(payload.user_id)?.userName;\n\n this.logToFile(targetChannelId, {\n date: createdAt.toISOString(),\n ts: eventTs,\n user: payload.user_id,\n userName,\n text: commandText,\n attachments: [],\n isBot: false,\n });\n\n if (!isDirectMessage) {\n await this.postEphemeral(\n sourceChannelId,\n payload.user_id,\n `我已私訊你 ${PRODUCT_NAME} 的登入連結,請到私訊完成設定。`,\n );\n }\n\n const event: BotEvent = {\n type: \"dm\",\n conversationId: targetChannelId,\n ...(isDirectMessage ? {} : { vaultConversationId: sourceChannelId }),\n conversationKind: \"direct\",\n ts: eventTs,\n user: payload.user_id,\n text: commandText,\n attachments: [],\n sessionKey: targetChannelId,\n };\n\n const adapters = this.createCommandAdapters(\n targetChannelId,\n payload.user_id,\n userName,\n commandText,\n eventTs,\n );\n\n await this.handler.handleEvent(event, this, adapters, false);\n }\n\n private async routeSlashNewCommand(payload: {\n command: string;\n channel_id: string;\n user_id: string;\n user_name?: string;\n }): Promise<void> {\n const conversationId = payload.channel_id;\n if (!conversationId.startsWith(\"D\")) {\n await this.postEphemeral(\n conversationId,\n payload.user_id,\n `為了避免誤清除共享上下文,${payload.command} 目前只能在與 ${PRODUCT_NAME} 的私訊中使用。`,\n );\n return;\n }\n\n const createdAt = new Date();\n const eventTs = (createdAt.getTime() / 1000).toFixed(6);\n const userName = payload.user_name ?? this.getUser(payload.user_id)?.userName;\n\n this.logToFile(conversationId, {\n date: createdAt.toISOString(),\n ts: eventTs,\n user: payload.user_id,\n userName,\n text: payload.command,\n attachments: [],\n isBot: false,\n });\n\n const commandBot = this.createSlashCommandBot(conversationId);\n await this.handler.handleNew(conversationId, conversationId, commandBot);\n }\n\n private async routeSlashSessionCommand(payload: {\n command: string;\n channel_id: string;\n user_id: string;\n user_name?: string;\n }): Promise<void> {\n const conversationId = payload.channel_id;\n const isDirectMessage = conversationId.startsWith(\"D\");\n const createdAt = new Date();\n const eventTs = (createdAt.getTime() / 1000).toFixed(6);\n const userName = payload.user_name ?? this.getUser(payload.user_id)?.userName;\n const commandText = payload.command;\n\n this.logToFile(conversationId, {\n date: createdAt.toISOString(),\n ts: eventTs,\n user: payload.user_id,\n userName,\n text: commandText,\n attachments: [],\n isBot: false,\n });\n\n const sessionKey = conversationId;\n const event: BotEvent = {\n type: \"dm\",\n conversationId,\n conversationKind: isDirectMessage ? \"direct\" : \"shared\",\n ts: eventTs,\n user: payload.user_id,\n text: commandText,\n attachments: [],\n sessionKey,\n };\n\n const adapters = this.createCommandAdapters(\n conversationId,\n payload.user_id,\n userName,\n commandText,\n eventTs,\n isDirectMessage ? {} : { ephemeralChannelId: conversationId },\n );\n\n await this.handler.handleEvent(event, this, adapters, false);\n }\n\n private setupEventHandlers(): void {\n // Channel @mentions\n this.socketClient.on(\"app_mention\", ({ event, ack }) => {\n const e = event as {\n text: string;\n channel: string;\n user: string;\n ts: string;\n thread_ts?: string;\n files?: Array<{ name: string; url_private_download?: string; url_private?: string }>;\n };\n\n // Skip DMs (handled by message event)\n if (e.channel.startsWith(\"D\")) {\n ack();\n return;\n }\n\n // Top-level mentions use a persistent channel session.\n // Thread replies get their own isolated session (channelId:thread_ts).\n const sessionKey = resolveSlackSessionKey(e.channel, e.thread_ts);\n\n const slackEvent: SlackEvent = {\n type: \"mention\",\n conversationId: e.channel,\n conversationKind: \"shared\",\n channel: e.channel,\n ts: e.ts,\n thread_ts: e.thread_ts,\n user: e.user,\n text: e.text.replace(/<@[A-Z0-9]+>/gi, \"\").trim(),\n files: e.files,\n sessionKey,\n };\n\n const attachmentsPromise = this.logUserMessage(slackEvent);\n\n // Only trigger processing for messages AFTER startup (not replayed old messages)\n if (this.startupTs && e.ts < this.startupTs) {\n log.logInfo(\n `[${e.channel}] Logged old message (pre-startup), not triggering: ${slackEvent.text.substring(0, 30)}`,\n );\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n // Check for stop command - execute immediately, don't queue!\n if (slackEvent.text.toLowerCase().trim() === \"stop\") {\n const stopTarget = this.resolveStopTarget(e.channel, e.thread_ts);\n if (stopTarget) {\n this.handler.handleStop(stopTarget, e.channel, this);\n } else {\n this.postMessage(e.channel, formatNothingRunning(\"slack\"));\n }\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n this.getQueue(this.resolveQueueKey(e.channel, sessionKey)).enqueue(async () => {\n slackEvent.attachments = await attachmentsPromise;\n const adapters = createSlackAdapters(slackEvent, this, false);\n return this.handler.handleEvent(\n slackEvent as unknown as import(\"../../adapter.js\").BotEvent,\n this,\n adapters,\n false,\n );\n });\n\n ack();\n });\n\n // All messages (for logging) + DMs (for triggering)\n this.socketClient.on(\"message\", ({ event, ack }) => {\n const e = event as {\n text?: string;\n channel: string;\n user?: string;\n ts: string;\n thread_ts?: string;\n channel_type?: string;\n subtype?: string;\n bot_id?: string;\n files?: Array<{ name: string; url_private_download?: string; url_private?: string }>;\n };\n\n // Skip bot messages, edits, etc.\n if (e.bot_id || !e.user || e.user === this.botUserId) {\n ack();\n return;\n }\n if (e.subtype !== undefined && e.subtype !== \"file_share\") {\n ack();\n return;\n }\n if (!e.text && (!e.files || e.files.length === 0)) {\n ack();\n return;\n }\n\n const isDM = e.channel_type === \"im\";\n const conversationKind: ConversationKind = isDM ? \"direct\" : \"shared\";\n const isBotMention = e.text?.includes(`<@${this.botUserId}>`);\n\n // Skip channel @mentions - already handled by app_mention event\n if (!isDM && isBotMention) {\n ack();\n return;\n }\n\n const isSharedThreadReply =\n !isDM && this.shouldTriggerSharedThreadReply(e.channel, e.thread_ts);\n const sessionKey =\n isDM || isSharedThreadReply ? resolveSlackSessionKey(e.channel, e.thread_ts) : undefined;\n\n const slackEvent: SlackEvent = {\n type: isDM ? \"dm\" : \"mention\",\n conversationId: e.channel,\n conversationKind,\n channel: e.channel,\n ts: e.ts,\n thread_ts: e.thread_ts,\n user: e.user,\n text: (e.text || \"\").replace(/<@[A-Z0-9]+>/gi, \"\").trim(),\n files: e.files,\n sessionKey,\n };\n\n const attachmentsPromise = this.logUserMessage(slackEvent);\n\n // Only trigger processing for messages AFTER startup (not replayed old messages)\n if (this.startupTs && e.ts < this.startupTs) {\n log.logInfo(\n `[${e.channel}] Skipping old message (pre-startup): ${slackEvent.text.substring(0, 30)}`,\n );\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n // Check for stop command in channel threads (without @mention)\n // app_mention handles \"@mama stop\", but bare \"stop\" in a thread comes here\n if (!isDM && e.thread_ts && slackEvent.text.toLowerCase().trim() === \"stop\") {\n const stopTarget = this.resolveStopTarget(e.channel, e.thread_ts);\n if (stopTarget) {\n this.handler.handleStop(stopTarget, e.channel, this);\n } else {\n this.postMessage(e.channel, formatNothingRunning(\"slack\"));\n }\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n // Trigger handler for DMs and bare replies inside shared-channel threads.\n if (isDM || isSharedThreadReply) {\n const activeSessionKey =\n slackEvent.sessionKey ?? resolveSlackSessionKey(e.channel, e.thread_ts);\n // Check for stop command - execute immediately, don't queue!\n if (slackEvent.text.toLowerCase().trim() === \"stop\") {\n const stopTarget = this.resolveStopTarget(e.channel, e.thread_ts);\n if (stopTarget) {\n this.handler.handleStop(stopTarget, e.channel, this); // Don't await, don't queue\n } else {\n this.postMessage(e.channel, formatNothingRunning(\"slack\"));\n }\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n ack();\n return;\n }\n\n this.getQueue(this.resolveQueueKey(e.channel, activeSessionKey)).enqueue(async () => {\n slackEvent.attachments = await attachmentsPromise;\n const adapters = createSlackAdapters(slackEvent, this, false);\n return this.handler.handleEvent(\n slackEvent as unknown as import(\"../../adapter.js\").BotEvent,\n this,\n adapters,\n false,\n );\n });\n } else {\n void attachmentsPromise.catch((err) => {\n log.logWarning(\"Failed to log Slack message\", String(err));\n });\n }\n\n ack();\n });\n\n this.socketClient.on(\"slash_commands\", async ({ body, ack }) => {\n const payload = body as {\n command?: string;\n text?: string;\n channel_id?: string;\n user_id?: string;\n user_name?: string;\n };\n\n await ack();\n\n if (!payload.command || !payload.channel_id || !payload.user_id) {\n return;\n }\n\n const handlerPromise =\n payload.command === \"/pi-login\"\n ? this.routeSlashLoginCommand({\n command: payload.command,\n text: payload.text,\n channel_id: payload.channel_id,\n user_id: payload.user_id,\n user_name: payload.user_name,\n })\n : payload.command === \"/pi-new\"\n ? this.routeSlashNewCommand({\n command: payload.command,\n channel_id: payload.channel_id,\n user_id: payload.user_id,\n user_name: payload.user_name,\n })\n : payload.command === \"/pi-session\"\n ? this.routeSlashSessionCommand({\n command: payload.command,\n channel_id: payload.channel_id,\n user_id: payload.user_id,\n user_name: payload.user_name,\n })\n : null;\n\n if (!handlerPromise) {\n return;\n }\n\n handlerPromise.catch((err) => {\n log.logWarning(\n \"Slack slash command error\",\n err instanceof Error ? err.message : String(err),\n );\n });\n });\n\n // App Home tab\n this.socketClient.on(\"app_home_opened\", ({ event, ack }) => {\n const e = event as { user: string; tab: string };\n ack();\n if (e.tab !== \"home\") return;\n\n this.webClient.views\n .publish({\n user_id: e.user,\n view: this.buildHomeView(),\n })\n .catch((err) => {\n log.logWarning(`Failed to publish App Home view`, String(err));\n });\n });\n\n // Handle button clicks (Force Stop)\n this.socketClient.on(\"block_actions\", async ({ body, ack }) => {\n const action = body.actions?.[0];\n if (!action || !action.action_id?.startsWith(\"force_stop_\")) {\n ack();\n return;\n }\n\n ack();\n const sessionKey = action.action_id.replace(\"force_stop_\", \"\").replace(/_/g, \":\");\n const userId = body.user?.id;\n const channelId = body.container?.channel_id || sessionKey.split(\":\")[0];\n\n log.logInfo(`[Force Stop] User ${userId} requested force stop for ${sessionKey}`);\n\n // Use handler's forceStop method\n this.handler.forceStop(sessionKey);\n\n // Notify in channel\n await this.postMessage(channelId, formatForceStopped(\"slack\", userId ?? \"unknown\"));\n\n // Refresh home tab\n if (userId) {\n this.webClient.views\n .publish({\n user_id: userId,\n view: this.buildHomeView(),\n })\n .catch((err) => {\n log.logWarning(`Failed to refresh App Home view`, String(err));\n });\n }\n });\n }\n\n /**\n * Log a user message to log.jsonl after attachments are ready.\n */\n private async logUserMessage(event: SlackEvent): Promise<Attachment[]> {\n const user = this.users.get(event.user);\n const attachments = event.files\n ? await this.store.processAttachments(event.channel, event.files, event.ts)\n : [];\n this.logToFile(event.channel, {\n date: new Date(parseFloat(event.ts) * 1000).toISOString(),\n ts: event.ts,\n threadTs: event.thread_ts,\n user: event.user,\n userName: user?.userName,\n displayName: user?.displayName,\n text: event.text,\n attachments,\n isBot: false,\n });\n return attachments;\n }\n\n // ==========================================================================\n // Private - Backfill\n // ==========================================================================\n\n private async getExistingTimestamps(channelId: string): Promise<Set<string>> {\n const logPath = join(this.workingDir, channelId, \"log.jsonl\");\n const timestamps = new Set<string>();\n if (!existsSync(logPath)) return timestamps;\n\n const content = await readFile(logPath, \"utf-8\");\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n for (let i = 0; i < lines.length; i++) {\n try {\n const entry = JSON.parse(lines[i]);\n if (entry.ts) timestamps.add(entry.ts);\n } catch (err) {\n log.logWarning(\n `Skipping malformed log entry at ${logPath}:${i + 1}`,\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n return timestamps;\n }\n\n private async backfillChannel(channelId: string): Promise<number> {\n const existingTs = await this.getExistingTimestamps(channelId);\n\n // Find the biggest ts in log.jsonl\n let latestTs: string | undefined;\n for (const ts of existingTs) {\n if (!latestTs || parseFloat(ts) > parseFloat(latestTs)) latestTs = ts;\n }\n\n type Message = {\n user?: string;\n bot_id?: string;\n text?: string;\n ts?: string;\n thread_ts?: string;\n subtype?: string;\n files?: Array<{ name: string }>;\n };\n const allMessages: Message[] = [];\n\n let cursor: string | undefined;\n let pageCount = 0;\n const maxPages = 3;\n\n do {\n const result = await this.webClient.conversations.history({\n channel: channelId,\n oldest: latestTs, // Only fetch messages newer than what we have\n inclusive: false,\n limit: 1000,\n cursor,\n });\n if (result.messages) {\n allMessages.push(...(result.messages as Message[]));\n }\n cursor = result.response_metadata?.next_cursor;\n pageCount++;\n } while (cursor && pageCount < maxPages);\n\n // Filter: include mama's messages, exclude other bots, skip already logged\n const relevantMessages = allMessages.filter((msg) => {\n if (!msg.ts || existingTs.has(msg.ts)) return false; // Skip duplicates\n if (msg.user === this.botUserId) return true;\n if (msg.bot_id) return false;\n if (msg.subtype !== undefined && msg.subtype !== \"file_share\") return false;\n if (!msg.user) return false;\n if (!msg.text && (!msg.files || msg.files.length === 0)) return false;\n return true;\n });\n\n // Reverse to chronological order\n relevantMessages.reverse();\n\n // Log each message to log.jsonl\n for (const msg of relevantMessages) {\n const isMamaMessage = msg.user === this.botUserId;\n const user = this.users.get(msg.user!);\n // Strip @mentions from text (same as live messages)\n const text = (msg.text || \"\").replace(/<@[A-Z0-9]+>/gi, \"\").trim();\n const attachments = msg.files\n ? await this.store.processAttachments(channelId, msg.files, msg.ts!)\n : [];\n\n this.logToFile(channelId, {\n date: new Date(parseFloat(msg.ts!) * 1000).toISOString(),\n ts: msg.ts!,\n threadTs: msg.thread_ts,\n user: isMamaMessage ? \"bot\" : msg.user!,\n userName: isMamaMessage ? undefined : user?.userName,\n displayName: isMamaMessage ? undefined : user?.displayName,\n text,\n attachments,\n isBot: isMamaMessage,\n });\n }\n\n return relevantMessages.length;\n }\n\n private async backfillAllChannels(): Promise<void> {\n const startTime = Date.now();\n\n // Only backfill channels that already have a log.jsonl (mama has interacted with them before)\n const channelsToBackfill: Array<[string, SlackChannel]> = [];\n for (const [channelId, channel] of this.channels) {\n const logPath = join(this.workingDir, channelId, \"log.jsonl\");\n if (existsSync(logPath)) {\n channelsToBackfill.push([channelId, channel]);\n }\n }\n\n log.logBackfillStart(channelsToBackfill.length);\n\n let totalMessages = 0;\n for (const [channelId, channel] of channelsToBackfill) {\n try {\n const count = await this.backfillChannel(channelId);\n if (count > 0) log.logBackfillChannel(channel.name, count);\n totalMessages += count;\n } catch (error) {\n log.logWarning(`Failed to backfill #${channel.name}`, String(error));\n }\n\n // Add delay between channels to avoid hitting Slack rate limits\n if (channelId !== channelsToBackfill[channelsToBackfill.length - 1][0]) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n }\n\n const durationMs = Date.now() - startTime;\n log.logBackfillComplete(totalMessages, durationMs);\n }\n\n // ==========================================================================\n // Private - Fetch Users/Channels\n // ==========================================================================\n\n private async fetchUsers(): Promise<void> {\n let cursor: string | undefined;\n do {\n const result = await this.webClient.users.list({ limit: 200, cursor });\n const members = result.members as\n | Array<{ id?: string; name?: string; real_name?: string; deleted?: boolean }>\n | undefined;\n if (members) {\n for (const u of members) {\n if (u.id && u.name && !u.deleted) {\n this.users.set(u.id, {\n id: u.id,\n userName: u.name,\n displayName: u.real_name || u.name,\n });\n }\n }\n }\n cursor = result.response_metadata?.next_cursor;\n } while (cursor);\n }\n\n private async fetchChannels(): Promise<void> {\n // Fetch public/private channels\n let cursor: string | undefined;\n do {\n const result = await this.webClient.conversations.list({\n types: \"public_channel,private_channel\",\n exclude_archived: true,\n limit: 200,\n cursor,\n });\n const channels = result.channels as\n | Array<{ id?: string; name?: string; is_member?: boolean }>\n | undefined;\n if (channels) {\n for (const c of channels) {\n if (c.id && c.name && c.is_member) {\n this.channels.set(c.id, { id: c.id, name: c.name });\n }\n }\n }\n cursor = result.response_metadata?.next_cursor;\n } while (cursor);\n\n // Also fetch DM channels (IMs)\n cursor = undefined;\n do {\n const result = await this.webClient.conversations.list({\n types: \"im\",\n limit: 200,\n cursor,\n });\n const ims = result.channels as Array<{ id?: string; user?: string }> | undefined;\n if (ims) {\n for (const im of ims) {\n if (im.id) {\n // Use user's name as channel name for DMs\n const user = im.user ? this.users.get(im.user) : undefined;\n const name = user ? `DM:${user.userName}` : `DM:${im.id}`;\n this.channels.set(im.id, { id: im.id, name });\n }\n }\n }\n cursor = result.response_metadata?.next_cursor;\n } while (cursor);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EAEnB,YAAY,EACb,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGrD,eAAO,MAAM,sBAAsB,wLAEmB,CAAC;AAyBvD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,QAAQ,EACf,OAAO,CAAC,EAAE,OAAO,GAChB;IACD,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,mBAAmB,CAAC;IACjC,QAAQ,EAAE,YAAY,CAAC;CACxB,CAmPA","sourcesContent":["import type {\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n PlatformInfo,\n} from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport { formatToolArgs, splitText } from \"../shared.js\";\nimport type { SlackBot, SlackEvent } from \"./bot.js\";\nimport { resolveSlackRootTs, resolveSlackSessionKey } from \"./session.js\";\n\nexport const SLACK_FORMATTING_GUIDE = `## Slack Formatting (mrkdwn, NOT Markdown)\nBold: *text*, Italic: _text_, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: <url|text>\nDo NOT use **double asterisks** or [markdown](links).`;\n\nconst MAX_MAIN_LENGTH = 35000; // Slack hard limit is 40k\nconst MAX_THREAD_LENGTH = 20000;\nconst TRUNCATION_NOTE_INCREMENTAL =\n \"\\n\\n_(message truncated, ask me to elaborate on specific parts)_\";\nconst TRUNCATION_NOTE_FINAL = \"\\n\\n_(see thread for full response)_\";\n\nconst formatSlackContinuation = (partNum: number): string => `_(continued ${partNum})_`;\n\nfunction isSlackMessageTs(ts: string | undefined): ts is string {\n return typeof ts === \"string\" && /^\\d+\\.\\d+$/.test(ts);\n}\n\nfunction formatSlackToolResult(result: ChatToolResult): string {\n const argsFormatted = formatToolArgs(result.args);\n const duration = (result.durationMs / 1000).toFixed(1);\n let text = `*${result.isError ? \"✗\" : \"✓\"} ${result.toolName}*`;\n if (result.label) text += `: ${result.label}`;\n text += ` (${duration}s)\\n`;\n if (argsFormatted) text += `\\`\\`\\`\\n${argsFormatted}\\n\\`\\`\\`\\n`;\n text += `*Result:*\\n\\`\\`\\`\\n${result.result}\\n\\`\\`\\``;\n return text;\n}\n\nexport function createSlackAdapters(\n event: SlackEvent,\n slack: SlackBot,\n isEvent?: boolean,\n): {\n message: ChatMessage;\n responseCtx: ChatResponseContext;\n platform: PlatformInfo;\n} {\n let messageTs: string | null = null;\n const threadMessageTs: string[] = [];\n let accumulatedText = \"\";\n let isWorking = true;\n const workingIndicator = \" ...\";\n let updatePromise = Promise.resolve();\n\n const channelId = event.channel;\n const conversationId = event.conversationId;\n const user = slack.getUser(event.user);\n\n // Extract event filename for status message\n const eventFilename = isEvent ? event.text.match(/^\\[EVENT:([^:]+):/)?.[1] : undefined;\n\n const rootTs =\n event.thread_ts ?? (isSlackMessageTs(event.ts) ? resolveSlackRootTs(event.ts) : undefined);\n const isThreaded = !!event.thread_ts;\n\n /**\n * Post the first visible reply.\n * Normal Slack messages reply in-thread under the triggering user message.\n * Synthetic event messages have no real Slack root ts, so they must post top-level.\n */\n const postFirstMessage = async (text: string): Promise<string> => {\n if (isEvent) {\n if (event.thread_ts) {\n return slack.postInThread(channelId, event.thread_ts, text);\n }\n return slack.postMessage(channelId, text);\n }\n return isSlackMessageTs(event.ts)\n ? slack.postInThread(channelId, event.ts, text)\n : slack.postMessage(channelId, text);\n };\n\n const postDiagnosticDirect = async (\n text: string,\n options?: { style?: \"muted\" | \"error\" },\n ): Promise<void> => {\n const threadAnchor = rootTs ?? messageTs;\n if (!threadAnchor) return;\n\n for (const part of splitText(text, MAX_THREAD_LENGTH, formatSlackContinuation)) {\n if (options?.style === \"muted\") {\n const CONTEXT_TEXT_LIMIT = 3000;\n const blockText =\n part.length > CONTEXT_TEXT_LIMIT\n ? part.substring(0, CONTEXT_TEXT_LIMIT - 20) + \"\\n_(truncated)_\"\n : part;\n const ts = await slack.postInThreadBlocks(channelId, threadAnchor, part, [\n { type: \"context\", elements: [{ type: \"mrkdwn\", text: blockText }] },\n ]);\n threadMessageTs.push(ts);\n } else {\n const diagnosticText = options?.style === \"error\" ? `_${part}_` : part;\n const ts = await slack.postInThread(channelId, threadAnchor, diagnosticText);\n threadMessageTs.push(ts);\n }\n }\n };\n\n const message: ChatMessage = {\n id: event.ts,\n sessionKey: event.sessionKey ?? resolveSlackSessionKey(conversationId, event.thread_ts),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: user?.userName,\n text: event.text,\n attachments: (event.attachments || []).map((a) => ({\n name: a.original,\n localPath: a.localPath,\n })),\n threadTs: event.thread_ts,\n };\n\n const platform: PlatformInfo = {\n name: \"slack\",\n formattingGuide: SLACK_FORMATTING_GUIDE,\n channels: slack.getAllChannels().map((c) => ({ id: c.id, name: c.name })),\n users: slack\n .getAllUsers()\n .map((u) => ({ id: u.id, userName: u.userName, displayName: u.displayName })),\n diagnostics: {\n showUsageSummary: true,\n },\n };\n\n const responseCtx = {\n respond: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${text}` : text;\n\n if (accumulatedText.length > MAX_MAIN_LENGTH) {\n accumulatedText =\n accumulatedText.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_INCREMENTAL.length) +\n TRUNCATION_NOTE_INCREMENTAL;\n }\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n // Reply within the user's thread\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (messageTs) {\n slack.logBotResponse(channelId, text, messageTs, isThreaded ? rootTs : undefined);\n }\n } catch (err) {\n log.logWarning(\"Slack respond error\", err instanceof Error ? err.message : String(err));\n }\n });\n await updatePromise;\n },\n\n replaceResponse: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n const overflowed = text.length > MAX_MAIN_LENGTH;\n accumulatedText = overflowed\n ? text.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_FINAL.length) +\n TRUNCATION_NOTE_FINAL\n : text;\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (overflowed) {\n await postDiagnosticDirect(text);\n }\n } catch (err) {\n log.logWarning(\n \"Slack replaceResponse error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondDiagnostic: async (text: string, options?: { style?: \"muted\" | \"error\" }) => {\n updatePromise = updatePromise.then(async () => {\n try {\n await postDiagnosticDirect(text, options);\n } catch (err) {\n log.logWarning(\n \"Slack respondDiagnostic error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondToolResult: async (result: ChatToolResult) => {\n await responseCtx.respondDiagnostic(formatSlackToolResult(result));\n },\n\n setTyping: async (isTyping: boolean) => {\n if (isTyping && !messageTs && rootTs) {\n try {\n const statusText = eventFilename ? `Starting event: ${eventFilename}` : \"Thinking\";\n await slack.setAssistantStatus(channelId, rootTs, statusText);\n } catch {\n // Assistant API not available — first respond() call will create the message\n }\n }\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n await slack.uploadFile(channelId, filePath, title, rootTs);\n },\n\n setWorking: async (working: boolean) => {\n updatePromise = updatePromise.then(async () => {\n try {\n isWorking = working;\n if (messageTs) {\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n const updates: Promise<void>[] = [\n slack.updateMessage(channelId, messageTs, displayText),\n ];\n if (!working) {\n if (rootTs) {\n updates.push(slack.setAssistantStatus(channelId, rootTs, \"\").catch(() => {}));\n }\n }\n await Promise.all(updates);\n }\n } catch (err) {\n log.logWarning(\n \"Slack setWorking error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n deleteResponse: async () => {\n updatePromise = updatePromise.then(async () => {\n // Clear assistant status first\n if (rootTs) {\n try {\n await slack.setAssistantStatus(channelId, rootTs, \"\");\n } catch {\n // Ignore errors clearing status\n }\n }\n\n // Delete thread messages first (in reverse order)\n for (let i = threadMessageTs.length - 1; i >= 0; i--) {\n try {\n await slack.deleteMessage(channelId, threadMessageTs[i]);\n } catch {\n // Ignore errors deleting thread messages\n }\n }\n threadMessageTs.length = 0;\n // Then delete main message\n if (messageTs) {\n await slack.deleteMessage(channelId, messageTs);\n messageTs = null;\n }\n });\n await updatePromise;\n },\n };\n\n return { message, responseCtx, platform };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EAEnB,YAAY,EACb,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGrD,eAAO,MAAM,sBAAsB,wLAEmB,CAAC;AAyBvD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,QAAQ,EACf,OAAO,CAAC,EAAE,OAAO,GAChB;IACD,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,mBAAmB,CAAC;IACjC,QAAQ,EAAE,YAAY,CAAC;CACxB,CAiQA","sourcesContent":["import type {\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n PlatformInfo,\n} from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport { formatToolArgs, splitText } from \"../shared.js\";\nimport type { SlackBot, SlackEvent } from \"./bot.js\";\nimport { resolveSlackRootTs, resolveSlackSessionKey } from \"./session.js\";\n\nexport const SLACK_FORMATTING_GUIDE = `## Slack Formatting (mrkdwn, NOT Markdown)\nBold: *text*, Italic: _text_, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: <url|text>\nDo NOT use **double asterisks** or [markdown](links).`;\n\nconst MAX_MAIN_LENGTH = 35000; // Slack hard limit is 40k\nconst MAX_THREAD_LENGTH = 20000;\nconst TRUNCATION_NOTE_INCREMENTAL =\n \"\\n\\n_(message truncated, ask me to elaborate on specific parts)_\";\nconst TRUNCATION_NOTE_FINAL = \"\\n\\n_(see thread for full response)_\";\n\nconst formatSlackContinuation = (partNum: number): string => `_(continued ${partNum})_`;\n\nfunction isSlackMessageTs(ts: string | undefined): ts is string {\n return typeof ts === \"string\" && /^\\d+\\.\\d+$/.test(ts);\n}\n\nfunction formatSlackToolResult(result: ChatToolResult): string {\n const argsFormatted = formatToolArgs(result.args);\n const duration = (result.durationMs / 1000).toFixed(1);\n let text = `*${result.isError ? \"✗\" : \"✓\"} ${result.toolName}*`;\n if (result.label) text += `: ${result.label}`;\n text += ` (${duration}s)\\n`;\n if (argsFormatted) text += `\\`\\`\\`\\n${argsFormatted}\\n\\`\\`\\`\\n`;\n text += `*Result:*\\n\\`\\`\\`\\n${result.result}\\n\\`\\`\\``;\n return text;\n}\n\nexport function createSlackAdapters(\n event: SlackEvent,\n slack: SlackBot,\n isEvent?: boolean,\n): {\n message: ChatMessage;\n responseCtx: ChatResponseContext;\n platform: PlatformInfo;\n} {\n let messageTs: string | null = null;\n let assistantStatusFailureWarned = false;\n const onAssistantStatusError = (label: string, err: unknown): void => {\n if (assistantStatusFailureWarned) return;\n assistantStatusFailureWarned = true;\n log.logWarning(\n `Slack setAssistantStatus failed (${label}; further occurrences suppressed for this session)`,\n err instanceof Error ? err.message : String(err),\n );\n };\n const threadMessageTs: string[] = [];\n let accumulatedText = \"\";\n let isWorking = true;\n const workingIndicator = \" ...\";\n let updatePromise = Promise.resolve();\n\n const channelId = event.channel;\n const conversationId = event.conversationId;\n const user = slack.getUser(event.user);\n\n // Extract event filename for status message\n const eventFilename = isEvent ? event.text.match(/^\\[EVENT:([^:]+):/)?.[1] : undefined;\n\n const rootTs =\n event.thread_ts ?? (isSlackMessageTs(event.ts) ? resolveSlackRootTs(event.ts) : undefined);\n const isThreaded = !!event.thread_ts;\n\n /**\n * Post the first visible reply.\n * Normal Slack messages reply in-thread under the triggering user message.\n * Synthetic event messages have no real Slack root ts, so they must post top-level.\n */\n const postFirstMessage = async (text: string): Promise<string> => {\n if (isEvent) {\n if (event.thread_ts) {\n return slack.postInThread(channelId, event.thread_ts, text);\n }\n return slack.postMessage(channelId, text);\n }\n return isSlackMessageTs(event.ts)\n ? slack.postInThread(channelId, event.ts, text)\n : slack.postMessage(channelId, text);\n };\n\n const postDiagnosticDirect = async (\n text: string,\n options?: { style?: \"muted\" | \"error\" },\n ): Promise<void> => {\n const threadAnchor = rootTs ?? messageTs;\n if (!threadAnchor) return;\n\n for (const part of splitText(text, MAX_THREAD_LENGTH, formatSlackContinuation)) {\n if (options?.style === \"muted\") {\n const CONTEXT_TEXT_LIMIT = 3000;\n const blockText =\n part.length > CONTEXT_TEXT_LIMIT\n ? part.substring(0, CONTEXT_TEXT_LIMIT - 20) + \"\\n_(truncated)_\"\n : part;\n const ts = await slack.postInThreadBlocks(channelId, threadAnchor, part, [\n { type: \"context\", elements: [{ type: \"mrkdwn\", text: blockText }] },\n ]);\n threadMessageTs.push(ts);\n } else {\n const diagnosticText = options?.style === \"error\" ? `_${part}_` : part;\n const ts = await slack.postInThread(channelId, threadAnchor, diagnosticText);\n threadMessageTs.push(ts);\n }\n }\n };\n\n const message: ChatMessage = {\n id: event.ts,\n sessionKey: event.sessionKey ?? resolveSlackSessionKey(conversationId, event.thread_ts),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: user?.userName,\n text: event.text,\n attachments: (event.attachments || []).map((a) => ({\n name: a.original,\n localPath: a.localPath,\n })),\n threadTs: event.thread_ts,\n };\n\n const platform: PlatformInfo = {\n name: \"slack\",\n formattingGuide: SLACK_FORMATTING_GUIDE,\n channels: slack.getAllChannels().map((c) => ({ id: c.id, name: c.name })),\n users: slack\n .getAllUsers()\n .map((u) => ({ id: u.id, userName: u.userName, displayName: u.displayName })),\n diagnostics: {\n showUsageSummary: true,\n },\n };\n\n const responseCtx = {\n respond: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${text}` : text;\n\n if (accumulatedText.length > MAX_MAIN_LENGTH) {\n accumulatedText =\n accumulatedText.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_INCREMENTAL.length) +\n TRUNCATION_NOTE_INCREMENTAL;\n }\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n // Reply within the user's thread\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (messageTs) {\n slack.logBotResponse(channelId, text, messageTs, isThreaded ? rootTs : undefined);\n }\n } catch (err) {\n log.logWarning(\"Slack respond error\", err instanceof Error ? err.message : String(err));\n }\n });\n await updatePromise;\n },\n\n replaceResponse: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n const overflowed = text.length > MAX_MAIN_LENGTH;\n accumulatedText = overflowed\n ? text.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_FINAL.length) +\n TRUNCATION_NOTE_FINAL\n : text;\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (overflowed) {\n await postDiagnosticDirect(text);\n }\n } catch (err) {\n log.logWarning(\n \"Slack replaceResponse error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondDiagnostic: async (text: string, options?: { style?: \"muted\" | \"error\" }) => {\n updatePromise = updatePromise.then(async () => {\n try {\n await postDiagnosticDirect(text, options);\n } catch (err) {\n log.logWarning(\n \"Slack respondDiagnostic error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondToolResult: async (result: ChatToolResult) => {\n await responseCtx.respondDiagnostic(formatSlackToolResult(result));\n },\n\n setTyping: async (isTyping: boolean) => {\n if (isTyping && !messageTs && rootTs) {\n try {\n const statusText = eventFilename ? `Starting event: ${eventFilename}` : \"Thinking\";\n await slack.setAssistantStatus(channelId, rootTs, statusText);\n } catch (err) {\n // Assistant API not available — first respond() call will create the message.\n onAssistantStatusError(\"typing\", err);\n }\n }\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n await slack.uploadFile(channelId, filePath, title, rootTs);\n },\n\n setWorking: async (working: boolean) => {\n updatePromise = updatePromise.then(async () => {\n try {\n isWorking = working;\n if (messageTs) {\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n const updates: Promise<void>[] = [\n slack.updateMessage(channelId, messageTs, displayText),\n ];\n if (!working) {\n if (rootTs) {\n updates.push(\n slack\n .setAssistantStatus(channelId, rootTs, \"\")\n .catch((err) => onAssistantStatusError(\"clear-on-idle\", err)),\n );\n }\n }\n await Promise.all(updates);\n }\n } catch (err) {\n log.logWarning(\n \"Slack setWorking error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n deleteResponse: async () => {\n updatePromise = updatePromise.then(async () => {\n // Clear assistant status first\n if (rootTs) {\n try {\n await slack.setAssistantStatus(channelId, rootTs, \"\");\n } catch {\n // Ignore errors clearing status\n }\n }\n\n // Delete thread messages first (in reverse order)\n for (let i = threadMessageTs.length - 1; i >= 0; i--) {\n try {\n await slack.deleteMessage(channelId, threadMessageTs[i]);\n } catch {\n // Ignore errors deleting thread messages\n }\n }\n threadMessageTs.length = 0;\n // Then delete main message\n if (messageTs) {\n await slack.deleteMessage(channelId, messageTs);\n messageTs = null;\n }\n });\n await updatePromise;\n },\n };\n\n return { message, responseCtx, platform };\n}\n"]}
|
|
@@ -26,6 +26,13 @@ function formatSlackToolResult(result) {
|
|
|
26
26
|
}
|
|
27
27
|
export function createSlackAdapters(event, slack, isEvent) {
|
|
28
28
|
let messageTs = null;
|
|
29
|
+
let assistantStatusFailureWarned = false;
|
|
30
|
+
const onAssistantStatusError = (label, err) => {
|
|
31
|
+
if (assistantStatusFailureWarned)
|
|
32
|
+
return;
|
|
33
|
+
assistantStatusFailureWarned = true;
|
|
34
|
+
log.logWarning(`Slack setAssistantStatus failed (${label}; further occurrences suppressed for this session)`, err instanceof Error ? err.message : String(err));
|
|
35
|
+
};
|
|
29
36
|
const threadMessageTs = [];
|
|
30
37
|
let accumulatedText = "";
|
|
31
38
|
let isWorking = true;
|
|
@@ -179,8 +186,9 @@ export function createSlackAdapters(event, slack, isEvent) {
|
|
|
179
186
|
const statusText = eventFilename ? `Starting event: ${eventFilename}` : "Thinking";
|
|
180
187
|
await slack.setAssistantStatus(channelId, rootTs, statusText);
|
|
181
188
|
}
|
|
182
|
-
catch {
|
|
183
|
-
// Assistant API not available — first respond() call will create the message
|
|
189
|
+
catch (err) {
|
|
190
|
+
// Assistant API not available — first respond() call will create the message.
|
|
191
|
+
onAssistantStatusError("typing", err);
|
|
184
192
|
}
|
|
185
193
|
}
|
|
186
194
|
},
|
|
@@ -198,7 +206,9 @@ export function createSlackAdapters(event, slack, isEvent) {
|
|
|
198
206
|
];
|
|
199
207
|
if (!working) {
|
|
200
208
|
if (rootTs) {
|
|
201
|
-
updates.push(slack
|
|
209
|
+
updates.push(slack
|
|
210
|
+
.setAssistantStatus(channelId, rootTs, "")
|
|
211
|
+
.catch((err) => onAssistantStatusError("clear-on-idle", err)));
|
|
202
212
|
}
|
|
203
213
|
}
|
|
204
214
|
await Promise.all(updates);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/slack/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n PlatformInfo,\n} from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport { formatToolArgs, splitText } from \"../shared.js\";\nimport type { SlackBot, SlackEvent } from \"./bot.js\";\nimport { resolveSlackRootTs, resolveSlackSessionKey } from \"./session.js\";\n\nexport const SLACK_FORMATTING_GUIDE = `## Slack Formatting (mrkdwn, NOT Markdown)\nBold: *text*, Italic: _text_, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: <url|text>\nDo NOT use **double asterisks** or [markdown](links).`;\n\nconst MAX_MAIN_LENGTH = 35000; // Slack hard limit is 40k\nconst MAX_THREAD_LENGTH = 20000;\nconst TRUNCATION_NOTE_INCREMENTAL =\n \"\\n\\n_(message truncated, ask me to elaborate on specific parts)_\";\nconst TRUNCATION_NOTE_FINAL = \"\\n\\n_(see thread for full response)_\";\n\nconst formatSlackContinuation = (partNum: number): string => `_(continued ${partNum})_`;\n\nfunction isSlackMessageTs(ts: string | undefined): ts is string {\n return typeof ts === \"string\" && /^\\d+\\.\\d+$/.test(ts);\n}\n\nfunction formatSlackToolResult(result: ChatToolResult): string {\n const argsFormatted = formatToolArgs(result.args);\n const duration = (result.durationMs / 1000).toFixed(1);\n let text = `*${result.isError ? \"✗\" : \"✓\"} ${result.toolName}*`;\n if (result.label) text += `: ${result.label}`;\n text += ` (${duration}s)\\n`;\n if (argsFormatted) text += `\\`\\`\\`\\n${argsFormatted}\\n\\`\\`\\`\\n`;\n text += `*Result:*\\n\\`\\`\\`\\n${result.result}\\n\\`\\`\\``;\n return text;\n}\n\nexport function createSlackAdapters(\n event: SlackEvent,\n slack: SlackBot,\n isEvent?: boolean,\n): {\n message: ChatMessage;\n responseCtx: ChatResponseContext;\n platform: PlatformInfo;\n} {\n let messageTs: string | null = null;\n const threadMessageTs: string[] = [];\n let accumulatedText = \"\";\n let isWorking = true;\n const workingIndicator = \" ...\";\n let updatePromise = Promise.resolve();\n\n const channelId = event.channel;\n const conversationId = event.conversationId;\n const user = slack.getUser(event.user);\n\n // Extract event filename for status message\n const eventFilename = isEvent ? event.text.match(/^\\[EVENT:([^:]+):/)?.[1] : undefined;\n\n const rootTs =\n event.thread_ts ?? (isSlackMessageTs(event.ts) ? resolveSlackRootTs(event.ts) : undefined);\n const isThreaded = !!event.thread_ts;\n\n /**\n * Post the first visible reply.\n * Normal Slack messages reply in-thread under the triggering user message.\n * Synthetic event messages have no real Slack root ts, so they must post top-level.\n */\n const postFirstMessage = async (text: string): Promise<string> => {\n if (isEvent) {\n if (event.thread_ts) {\n return slack.postInThread(channelId, event.thread_ts, text);\n }\n return slack.postMessage(channelId, text);\n }\n return isSlackMessageTs(event.ts)\n ? slack.postInThread(channelId, event.ts, text)\n : slack.postMessage(channelId, text);\n };\n\n const postDiagnosticDirect = async (\n text: string,\n options?: { style?: \"muted\" | \"error\" },\n ): Promise<void> => {\n const threadAnchor = rootTs ?? messageTs;\n if (!threadAnchor) return;\n\n for (const part of splitText(text, MAX_THREAD_LENGTH, formatSlackContinuation)) {\n if (options?.style === \"muted\") {\n const CONTEXT_TEXT_LIMIT = 3000;\n const blockText =\n part.length > CONTEXT_TEXT_LIMIT\n ? part.substring(0, CONTEXT_TEXT_LIMIT - 20) + \"\\n_(truncated)_\"\n : part;\n const ts = await slack.postInThreadBlocks(channelId, threadAnchor, part, [\n { type: \"context\", elements: [{ type: \"mrkdwn\", text: blockText }] },\n ]);\n threadMessageTs.push(ts);\n } else {\n const diagnosticText = options?.style === \"error\" ? `_${part}_` : part;\n const ts = await slack.postInThread(channelId, threadAnchor, diagnosticText);\n threadMessageTs.push(ts);\n }\n }\n };\n\n const message: ChatMessage = {\n id: event.ts,\n sessionKey: event.sessionKey ?? resolveSlackSessionKey(conversationId, event.thread_ts),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: user?.userName,\n text: event.text,\n attachments: (event.attachments || []).map((a) => ({\n name: a.original,\n localPath: a.localPath,\n })),\n threadTs: event.thread_ts,\n };\n\n const platform: PlatformInfo = {\n name: \"slack\",\n formattingGuide: SLACK_FORMATTING_GUIDE,\n channels: slack.getAllChannels().map((c) => ({ id: c.id, name: c.name })),\n users: slack\n .getAllUsers()\n .map((u) => ({ id: u.id, userName: u.userName, displayName: u.displayName })),\n diagnostics: {\n showUsageSummary: true,\n },\n };\n\n const responseCtx = {\n respond: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${text}` : text;\n\n if (accumulatedText.length > MAX_MAIN_LENGTH) {\n accumulatedText =\n accumulatedText.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_INCREMENTAL.length) +\n TRUNCATION_NOTE_INCREMENTAL;\n }\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n // Reply within the user's thread\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (messageTs) {\n slack.logBotResponse(channelId, text, messageTs, isThreaded ? rootTs : undefined);\n }\n } catch (err) {\n log.logWarning(\"Slack respond error\", err instanceof Error ? err.message : String(err));\n }\n });\n await updatePromise;\n },\n\n replaceResponse: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n const overflowed = text.length > MAX_MAIN_LENGTH;\n accumulatedText = overflowed\n ? text.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_FINAL.length) +\n TRUNCATION_NOTE_FINAL\n : text;\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (overflowed) {\n await postDiagnosticDirect(text);\n }\n } catch (err) {\n log.logWarning(\n \"Slack replaceResponse error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondDiagnostic: async (text: string, options?: { style?: \"muted\" | \"error\" }) => {\n updatePromise = updatePromise.then(async () => {\n try {\n await postDiagnosticDirect(text, options);\n } catch (err) {\n log.logWarning(\n \"Slack respondDiagnostic error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondToolResult: async (result: ChatToolResult) => {\n await responseCtx.respondDiagnostic(formatSlackToolResult(result));\n },\n\n setTyping: async (isTyping: boolean) => {\n if (isTyping && !messageTs && rootTs) {\n try {\n const statusText = eventFilename ? `Starting event: ${eventFilename}` : \"Thinking\";\n await slack.setAssistantStatus(channelId, rootTs, statusText);\n } catch {\n // Assistant API not available — first respond() call will create the message\n }\n }\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n await slack.uploadFile(channelId, filePath, title, rootTs);\n },\n\n setWorking: async (working: boolean) => {\n updatePromise = updatePromise.then(async () => {\n try {\n isWorking = working;\n if (messageTs) {\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n const updates: Promise<void>[] = [\n slack.updateMessage(channelId, messageTs, displayText),\n ];\n if (!working) {\n if (rootTs) {\n updates.push(slack.setAssistantStatus(channelId, rootTs, \"\").catch(() => {}));\n }\n }\n await Promise.all(updates);\n }\n } catch (err) {\n log.logWarning(\n \"Slack setWorking error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n deleteResponse: async () => {\n updatePromise = updatePromise.then(async () => {\n // Clear assistant status first\n if (rootTs) {\n try {\n await slack.setAssistantStatus(channelId, rootTs, \"\");\n } catch {\n // Ignore errors clearing status\n }\n }\n\n // Delete thread messages first (in reverse order)\n for (let i = threadMessageTs.length - 1; i >= 0; i--) {\n try {\n await slack.deleteMessage(channelId, threadMessageTs[i]);\n } catch {\n // Ignore errors deleting thread messages\n }\n }\n threadMessageTs.length = 0;\n // Then delete main message\n if (messageTs) {\n await slack.deleteMessage(channelId, messageTs);\n messageTs = null;\n }\n });\n await updatePromise;\n },\n };\n\n return { message, responseCtx, platform };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/slack/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n PlatformInfo,\n} from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport { formatToolArgs, splitText } from \"../shared.js\";\nimport type { SlackBot, SlackEvent } from \"./bot.js\";\nimport { resolveSlackRootTs, resolveSlackSessionKey } from \"./session.js\";\n\nexport const SLACK_FORMATTING_GUIDE = `## Slack Formatting (mrkdwn, NOT Markdown)\nBold: *text*, Italic: _text_, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: <url|text>\nDo NOT use **double asterisks** or [markdown](links).`;\n\nconst MAX_MAIN_LENGTH = 35000; // Slack hard limit is 40k\nconst MAX_THREAD_LENGTH = 20000;\nconst TRUNCATION_NOTE_INCREMENTAL =\n \"\\n\\n_(message truncated, ask me to elaborate on specific parts)_\";\nconst TRUNCATION_NOTE_FINAL = \"\\n\\n_(see thread for full response)_\";\n\nconst formatSlackContinuation = (partNum: number): string => `_(continued ${partNum})_`;\n\nfunction isSlackMessageTs(ts: string | undefined): ts is string {\n return typeof ts === \"string\" && /^\\d+\\.\\d+$/.test(ts);\n}\n\nfunction formatSlackToolResult(result: ChatToolResult): string {\n const argsFormatted = formatToolArgs(result.args);\n const duration = (result.durationMs / 1000).toFixed(1);\n let text = `*${result.isError ? \"✗\" : \"✓\"} ${result.toolName}*`;\n if (result.label) text += `: ${result.label}`;\n text += ` (${duration}s)\\n`;\n if (argsFormatted) text += `\\`\\`\\`\\n${argsFormatted}\\n\\`\\`\\`\\n`;\n text += `*Result:*\\n\\`\\`\\`\\n${result.result}\\n\\`\\`\\``;\n return text;\n}\n\nexport function createSlackAdapters(\n event: SlackEvent,\n slack: SlackBot,\n isEvent?: boolean,\n): {\n message: ChatMessage;\n responseCtx: ChatResponseContext;\n platform: PlatformInfo;\n} {\n let messageTs: string | null = null;\n let assistantStatusFailureWarned = false;\n const onAssistantStatusError = (label: string, err: unknown): void => {\n if (assistantStatusFailureWarned) return;\n assistantStatusFailureWarned = true;\n log.logWarning(\n `Slack setAssistantStatus failed (${label}; further occurrences suppressed for this session)`,\n err instanceof Error ? err.message : String(err),\n );\n };\n const threadMessageTs: string[] = [];\n let accumulatedText = \"\";\n let isWorking = true;\n const workingIndicator = \" ...\";\n let updatePromise = Promise.resolve();\n\n const channelId = event.channel;\n const conversationId = event.conversationId;\n const user = slack.getUser(event.user);\n\n // Extract event filename for status message\n const eventFilename = isEvent ? event.text.match(/^\\[EVENT:([^:]+):/)?.[1] : undefined;\n\n const rootTs =\n event.thread_ts ?? (isSlackMessageTs(event.ts) ? resolveSlackRootTs(event.ts) : undefined);\n const isThreaded = !!event.thread_ts;\n\n /**\n * Post the first visible reply.\n * Normal Slack messages reply in-thread under the triggering user message.\n * Synthetic event messages have no real Slack root ts, so they must post top-level.\n */\n const postFirstMessage = async (text: string): Promise<string> => {\n if (isEvent) {\n if (event.thread_ts) {\n return slack.postInThread(channelId, event.thread_ts, text);\n }\n return slack.postMessage(channelId, text);\n }\n return isSlackMessageTs(event.ts)\n ? slack.postInThread(channelId, event.ts, text)\n : slack.postMessage(channelId, text);\n };\n\n const postDiagnosticDirect = async (\n text: string,\n options?: { style?: \"muted\" | \"error\" },\n ): Promise<void> => {\n const threadAnchor = rootTs ?? messageTs;\n if (!threadAnchor) return;\n\n for (const part of splitText(text, MAX_THREAD_LENGTH, formatSlackContinuation)) {\n if (options?.style === \"muted\") {\n const CONTEXT_TEXT_LIMIT = 3000;\n const blockText =\n part.length > CONTEXT_TEXT_LIMIT\n ? part.substring(0, CONTEXT_TEXT_LIMIT - 20) + \"\\n_(truncated)_\"\n : part;\n const ts = await slack.postInThreadBlocks(channelId, threadAnchor, part, [\n { type: \"context\", elements: [{ type: \"mrkdwn\", text: blockText }] },\n ]);\n threadMessageTs.push(ts);\n } else {\n const diagnosticText = options?.style === \"error\" ? `_${part}_` : part;\n const ts = await slack.postInThread(channelId, threadAnchor, diagnosticText);\n threadMessageTs.push(ts);\n }\n }\n };\n\n const message: ChatMessage = {\n id: event.ts,\n sessionKey: event.sessionKey ?? resolveSlackSessionKey(conversationId, event.thread_ts),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: user?.userName,\n text: event.text,\n attachments: (event.attachments || []).map((a) => ({\n name: a.original,\n localPath: a.localPath,\n })),\n threadTs: event.thread_ts,\n };\n\n const platform: PlatformInfo = {\n name: \"slack\",\n formattingGuide: SLACK_FORMATTING_GUIDE,\n channels: slack.getAllChannels().map((c) => ({ id: c.id, name: c.name })),\n users: slack\n .getAllUsers()\n .map((u) => ({ id: u.id, userName: u.userName, displayName: u.displayName })),\n diagnostics: {\n showUsageSummary: true,\n },\n };\n\n const responseCtx = {\n respond: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${text}` : text;\n\n if (accumulatedText.length > MAX_MAIN_LENGTH) {\n accumulatedText =\n accumulatedText.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_INCREMENTAL.length) +\n TRUNCATION_NOTE_INCREMENTAL;\n }\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n // Reply within the user's thread\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (messageTs) {\n slack.logBotResponse(channelId, text, messageTs, isThreaded ? rootTs : undefined);\n }\n } catch (err) {\n log.logWarning(\"Slack respond error\", err instanceof Error ? err.message : String(err));\n }\n });\n await updatePromise;\n },\n\n replaceResponse: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n const overflowed = text.length > MAX_MAIN_LENGTH;\n accumulatedText = overflowed\n ? text.substring(0, MAX_MAIN_LENGTH - TRUNCATION_NOTE_FINAL.length) +\n TRUNCATION_NOTE_FINAL\n : text;\n\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageTs) {\n await slack.updateMessage(channelId, messageTs, displayText);\n } else if (isThreaded && rootTs) {\n messageTs = await slack.postInThread(channelId, rootTs, displayText);\n } else {\n messageTs = await postFirstMessage(displayText);\n }\n\n if (overflowed) {\n await postDiagnosticDirect(text);\n }\n } catch (err) {\n log.logWarning(\n \"Slack replaceResponse error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondDiagnostic: async (text: string, options?: { style?: \"muted\" | \"error\" }) => {\n updatePromise = updatePromise.then(async () => {\n try {\n await postDiagnosticDirect(text, options);\n } catch (err) {\n log.logWarning(\n \"Slack respondDiagnostic error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n respondToolResult: async (result: ChatToolResult) => {\n await responseCtx.respondDiagnostic(formatSlackToolResult(result));\n },\n\n setTyping: async (isTyping: boolean) => {\n if (isTyping && !messageTs && rootTs) {\n try {\n const statusText = eventFilename ? `Starting event: ${eventFilename}` : \"Thinking\";\n await slack.setAssistantStatus(channelId, rootTs, statusText);\n } catch (err) {\n // Assistant API not available — first respond() call will create the message.\n onAssistantStatusError(\"typing\", err);\n }\n }\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n await slack.uploadFile(channelId, filePath, title, rootTs);\n },\n\n setWorking: async (working: boolean) => {\n updatePromise = updatePromise.then(async () => {\n try {\n isWorking = working;\n if (messageTs) {\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n const updates: Promise<void>[] = [\n slack.updateMessage(channelId, messageTs, displayText),\n ];\n if (!working) {\n if (rootTs) {\n updates.push(\n slack\n .setAssistantStatus(channelId, rootTs, \"\")\n .catch((err) => onAssistantStatusError(\"clear-on-idle\", err)),\n );\n }\n }\n await Promise.all(updates);\n }\n } catch (err) {\n log.logWarning(\n \"Slack setWorking error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n deleteResponse: async () => {\n updatePromise = updatePromise.then(async () => {\n // Clear assistant status first\n if (rootTs) {\n try {\n await slack.setAssistantStatus(channelId, rootTs, \"\");\n } catch {\n // Ignore errors clearing status\n }\n }\n\n // Delete thread messages first (in reverse order)\n for (let i = threadMessageTs.length - 1; i >= 0; i--) {\n try {\n await slack.deleteMessage(channelId, threadMessageTs[i]);\n } catch {\n // Ignore errors deleting thread messages\n }\n }\n threadMessageTs.length = 0;\n // Then delete main message\n if (messageTs) {\n await slack.deleteMessage(channelId, messageTs);\n messageTs = null;\n }\n });\n await updatePromise;\n },\n };\n\n return { message, responseCtx, platform };\n}\n"]}
|