relaybot 1.0.4 → 1.0.6
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 +8 -6
- package/manifest.json +3 -1
- package/package.json +1 -1
- package/src/slack-handlers.js +25 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# RelayBot
|
|
2
2
|
|
|
3
|
-
An AI assistant that lives in your Slack DMs — powered by Claude or Codex.
|
|
3
|
+
An AI assistant that lives in your Slack channels and DMs — powered by Claude or Codex.
|
|
4
4
|
|
|
5
5
|
<img src="demo/demo.jpg" width="30%">
|
|
6
6
|
|
|
@@ -8,11 +8,11 @@ An AI assistant that lives in your Slack DMs — powered by Claude or Codex.
|
|
|
8
8
|
|
|
9
9
|
## What is RelayBot?
|
|
10
10
|
|
|
11
|
-
RelayBot acts as a bridge between Slack and AI coding agents, allowing you to interact with Claude or Codex
|
|
11
|
+
RelayBot acts as a bridge between Slack and AI coding agents, allowing you to interact with Claude or Codex by mentioning the bot in channels or sending a DM. Instead of switching between tools, you can request code changes, ask questions, and manage development tasks without leaving Slack.
|
|
12
12
|
|
|
13
13
|
### Key Features
|
|
14
14
|
|
|
15
|
-
- **Conversational AI Access** — Chat with Claude or Codex
|
|
15
|
+
- **Conversational AI Access** — Chat with Claude or Codex from Slack channels via mentions or via DM
|
|
16
16
|
- **Code Execution** — AI can read, write, and modify code in your projects
|
|
17
17
|
- **Task Automation** — Request file changes, refactoring, bug fixes, or new features
|
|
18
18
|
- **Context-Aware Responses** — Maintains project directory context across conversations
|
|
@@ -37,7 +37,7 @@ RelayBot acts as a bridge between Slack and AI coding agents, allowing you to in
|
|
|
37
37
|
│ SLACK │
|
|
38
38
|
│ ┌──────────┐ ┌──────────────┐ │
|
|
39
39
|
│ │ User │ ───── sends message ─────────────► │ Channel/ │ │
|
|
40
|
-
│ │ │ ◄──── receives reply ───────────── │
|
|
40
|
+
│ │ │ ◄──── receives reply ───────────── │ Channel │ │
|
|
41
41
|
│ └──────────┘ └──────────────┘ │
|
|
42
42
|
└─────────────────────────────────────────────────────────────────────┘
|
|
43
43
|
│ ▲
|
|
@@ -84,12 +84,12 @@ RelayBot acts as a bridge between Slack and AI coding agents, allowing you to in
|
|
|
84
84
|
|
|
85
85
|
## How It Works
|
|
86
86
|
|
|
87
|
-
1. **Slack Connection** — RelayBot connects to Slack via WebSocket (Socket Mode) and listens for DMs
|
|
87
|
+
1. **Slack Connection** — RelayBot connects to Slack via WebSocket (Socket Mode) and listens for mentions and DMs
|
|
88
88
|
2. **Message Reception** — When you send a message, Slack forwards it to RelayBot
|
|
89
89
|
3. **AI Bridge** — RelayBot spawns a persistent Claude or Codex CLI session and forwards your message
|
|
90
90
|
4. **AI Processing** — The AI processes your request with full access to your codebase
|
|
91
91
|
5. **Response Summarization** — Long outputs are summarized into concise, actionable messages
|
|
92
|
-
6. **Slack Reply** — The summarized response is sent back to
|
|
92
|
+
6. **Slack Reply** — The summarized response is sent back to the same channel or DM
|
|
93
93
|
|
|
94
94
|
---
|
|
95
95
|
|
|
@@ -215,6 +215,7 @@ Socket Mode allows the bot to receive events via WebSocket instead of HTTP endpo
|
|
|
215
215
|
2. Scroll to **Scopes** → **Bot Token Scopes**
|
|
216
216
|
3. Add these scopes:
|
|
217
217
|
- `chat:write` — Send messages
|
|
218
|
+
- `app_mentions:read` — Read mentions of your app
|
|
218
219
|
- `im:history` — Read DM history
|
|
219
220
|
- `im:read` — View DM metadata
|
|
220
221
|
- `im:write` — Start DMs with users
|
|
@@ -226,6 +227,7 @@ Socket Mode allows the bot to receive events via WebSocket instead of HTTP endpo
|
|
|
226
227
|
2. Toggle **Enable Events** to ON
|
|
227
228
|
3. Expand **Subscribe to bot events**
|
|
228
229
|
4. Add these events:
|
|
230
|
+
- `app_mention` — Receive mentions in channels
|
|
229
231
|
- `message.im` — Receive DM messages
|
|
230
232
|
|
|
231
233
|
#### 5. Install the App
|
package/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"display_information": {
|
|
3
3
|
"name": "RelayBot",
|
|
4
|
-
"description": "An AI assistant that lives in your Slack DMs — powered by Claude or Codex",
|
|
4
|
+
"description": "An AI assistant that lives in your Slack channels and DMs — powered by Claude or Codex",
|
|
5
5
|
"background_color": "#4A154B"
|
|
6
6
|
},
|
|
7
7
|
"features": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"scopes": {
|
|
15
15
|
"bot": [
|
|
16
16
|
"chat:write",
|
|
17
|
+
"app_mentions:read",
|
|
17
18
|
"im:history",
|
|
18
19
|
"im:read",
|
|
19
20
|
"im:write",
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
"settings": {
|
|
25
26
|
"event_subscriptions": {
|
|
26
27
|
"bot_events": [
|
|
28
|
+
"app_mention",
|
|
27
29
|
"message.im"
|
|
28
30
|
]
|
|
29
31
|
},
|
package/package.json
CHANGED
package/src/slack-handlers.js
CHANGED
|
@@ -24,13 +24,18 @@ function storeLastMessage(message) {
|
|
|
24
24
|
|
|
25
25
|
function getPromptSuffix() {
|
|
26
26
|
if (isProduction) {
|
|
27
|
-
return `\nIMPORTANT:
|
|
27
|
+
return `\nIMPORTANT: Read and follow the instructions in ${skillPath}`;
|
|
28
28
|
}
|
|
29
29
|
return '\nIMPORTANT: Use the relay-bot skill.';
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function stripMentions(text) {
|
|
33
|
+
if (!text) return text;
|
|
34
|
+
return text.replace(/<@[^>]+>/g, '').replace(/\s+/g, ' ').trim();
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
function registerHandlers(app) {
|
|
33
|
-
|
|
38
|
+
async function handleMessage({ message, say, text }) {
|
|
34
39
|
// Only respond to messages from the configured user
|
|
35
40
|
if (config.SLACK_USER_ID && message.user !== config.SLACK_USER_ID) {
|
|
36
41
|
return;
|
|
@@ -39,11 +44,28 @@ function registerHandlers(app) {
|
|
|
39
44
|
storeLastMessage(message);
|
|
40
45
|
|
|
41
46
|
if (agent.isRunning()) {
|
|
42
|
-
const fullPrompt =
|
|
47
|
+
const fullPrompt = text + getPromptSuffix();
|
|
43
48
|
agent.sendCommand(fullPrompt);
|
|
44
49
|
} else {
|
|
45
50
|
await say('Agent process is not running.');
|
|
46
51
|
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
app.event('app_mention', async ({ event, say }) => {
|
|
55
|
+
if (event.channel_type === 'im' || event.channel_type === 'mpim') {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const cleanedText = stripMentions(event.text);
|
|
60
|
+
await handleMessage({ message: event, say, text: cleanedText });
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
app.message(async ({ message, say }) => {
|
|
64
|
+
if (message.channel_type !== 'im') {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await handleMessage({ message, say, text: message.text });
|
|
47
69
|
});
|
|
48
70
|
}
|
|
49
71
|
|