summaryrefslogtreecommitdiffhomepage
path: root/packages/slack/src
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-10-14 02:53:55 -0400
committerDax Raad <[email protected]>2025-10-14 02:53:55 -0400
commit1923ddab6eebbd5b817a88574deda7cb7f94e782 (patch)
tree10e1e54e8b106b67b64346cc5b23a12fa3775deb /packages/slack/src
parentb8249cde4b1c5ed73daf31c002f9f5e2b2e3c89b (diff)
downloadopencode-1923ddab6eebbd5b817a88574deda7cb7f94e782.tar.gz
opencode-1923ddab6eebbd5b817a88574deda7cb7f94e782.zip
feat: add Slack integration package with Bolt framework
Diffstat (limited to 'packages/slack/src')
-rw-r--r--packages/slack/src/index.ts105
1 files changed, 105 insertions, 0 deletions
diff --git a/packages/slack/src/index.ts b/packages/slack/src/index.ts
new file mode 100644
index 000000000..e86b8fec5
--- /dev/null
+++ b/packages/slack/src/index.ts
@@ -0,0 +1,105 @@
+import { App } from "@slack/bolt"
+import { createOpencode } from "@opencode-ai/sdk"
+
+const app = new App({
+ token: process.env.SLACK_BOT_TOKEN,
+ signingSecret: process.env.SLACK_SIGNING_SECRET,
+ socketMode: true,
+ appToken: process.env.SLACK_APP_TOKEN,
+})
+
+console.log("๐Ÿ”ง Bot configuration:")
+console.log("- Bot token present:", !!process.env.SLACK_BOT_TOKEN)
+console.log("- Signing secret present:", !!process.env.SLACK_SIGNING_SECRET)
+console.log("- App token present:", !!process.env.SLACK_APP_TOKEN)
+
+console.log("๐Ÿš€ Starting opencode server...")
+const opencode = await createOpencode({
+ port: 0,
+})
+console.log("โœ… Opencode server ready")
+
+const sessions = new Map<string, { client: any; server: any; sessionId: string; channel: string; thread: string }>()
+
+app.use(async ({ next, context }) => {
+ console.log("๐Ÿ“ก Raw Slack event:", JSON.stringify(context, null, 2))
+ await next()
+})
+
+app.message(async ({ message, say }) => {
+ console.log("๐Ÿ“จ Received message event:", JSON.stringify(message, null, 2))
+
+ if (message.subtype || !("text" in message) || !message.text) {
+ console.log("โญ๏ธ Skipping message - no text or has subtype")
+ return
+ }
+
+ console.log("โœ… Processing message:", message.text)
+
+ const channel = message.channel
+ const thread = (message as any).thread_ts || message.ts
+ const sessionKey = `${channel}-${thread}`
+
+ let session = sessions.get(sessionKey)
+
+ if (!session) {
+ console.log("๐Ÿ†• Creating new opencode session...")
+ const { client, server } = opencode
+
+ const createResult = await client.session.create({
+ body: { title: `Slack thread ${thread}` },
+ })
+
+ if (createResult.error) {
+ console.error("โŒ Failed to create session:", createResult.error)
+ await say({ text: "Sorry, I had trouble creating a session. Please try again.", thread_ts: thread })
+ return
+ }
+
+ console.log("โœ… Created opencode session:", createResult.data.id)
+ session = { client, server, sessionId: createResult.data.id, channel, thread }
+ sessions.set(sessionKey, session)
+
+ const shareResult = await client.session.share({ path: { id: createResult.data.id } })
+ if (!shareResult.error && shareResult.data) {
+ const sessionUrl = shareResult.data.share?.url!
+ console.log("๐Ÿ”— Session shared:", sessionUrl)
+ await app.client.chat.postMessage({ channel, thread_ts: thread, text: sessionUrl })
+ }
+ }
+
+ console.log("๐Ÿ“ Sending to opencode:", message.text)
+ const result = await session.client.session.prompt({
+ path: { id: session.sessionId },
+ body: { parts: [{ type: "text", text: message.text }] },
+ })
+
+ console.log("๐Ÿ“ค Opencode response:", JSON.stringify(result, null, 2))
+
+ if (result.error) {
+ console.error("โŒ Failed to send message:", result.error)
+ await say({ text: "Sorry, I had trouble processing your message. Please try again.", thread_ts: thread })
+ return
+ }
+
+ const response = result.data
+ const responseText =
+ response.info?.content ||
+ response.parts
+ ?.filter((p: any) => p.type === "text")
+ .map((p: any) => p.text)
+ .join("\n") ||
+ "I received your message but didn't have a response."
+
+ console.log("๐Ÿ’ฌ Sending response:", responseText)
+ await say({ text: responseText, thread_ts: thread })
+})
+
+app.command("/test", async ({ command, ack, say }) => {
+ await ack()
+ console.log("๐Ÿงช Test command received:", JSON.stringify(command, null, 2))
+ await say("๐Ÿค– Bot is working! I can hear you loud and clear.")
+})
+
+await app.start()
+console.log("โšก๏ธ Slack bot is running!")