ccgateway 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +252 -0
- package/bin/ccg-dev.sh +3 -0
- package/dist/agents.d.ts +17 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +45 -0
- package/dist/agents.js.map +1 -0
- package/dist/chat.d.ts +14 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +104 -0
- package/dist/chat.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +501 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +70 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +45 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +201 -0
- package/dist/context.js.map +1 -0
- package/dist/daemon.d.ts +27 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +207 -0
- package/dist/daemon.js.map +1 -0
- package/dist/heartbeat.d.ts +42 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +153 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/logger.d.ts +15 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +70 -0
- package/dist/logger.js.map +1 -0
- package/dist/messaging.d.ts +43 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/messaging.js +132 -0
- package/dist/messaging.js.map +1 -0
- package/dist/migrate.d.ts +24 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +356 -0
- package/dist/migrate.js.map +1 -0
- package/dist/plugin.d.ts +63 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +93 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugins/discord-gateway.d.ts +32 -0
- package/dist/plugins/discord-gateway.d.ts.map +1 -0
- package/dist/plugins/discord-gateway.js +208 -0
- package/dist/plugins/discord-gateway.js.map +1 -0
- package/dist/plugins/slack-gateway.d.ts +35 -0
- package/dist/plugins/slack-gateway.d.ts.map +1 -0
- package/dist/plugins/slack-gateway.js +291 -0
- package/dist/plugins/slack-gateway.js.map +1 -0
- package/dist/router.d.ts +44 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +103 -0
- package/dist/router.js.map +1 -0
- package/dist/sessions.d.ts +55 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +160 -0
- package/dist/sessions.js.map +1 -0
- package/dist/skills.d.ts +58 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +194 -0
- package/dist/skills.js.map +1 -0
- package/dist/spawner.d.ts +29 -0
- package/dist/spawner.d.ts.map +1 -0
- package/dist/spawner.js +54 -0
- package/dist/spawner.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { Client, GatewayIntentBits } from "discord.js";
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
|
+
// ── Helpers (exported for testing) ────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a token value. If it starts with "$", treat it as an env var name.
|
|
6
|
+
* Throws if the env var is not set.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveToken(token) {
|
|
9
|
+
if (token.startsWith("$")) {
|
|
10
|
+
const envName = token.slice(1);
|
|
11
|
+
const value = process.env[envName];
|
|
12
|
+
if (!value) {
|
|
13
|
+
throw new Error(`Environment variable "${envName}" is not set (referenced by token "${token}")`);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
return token;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Smart message splitter for Discord's 2000-char limit.
|
|
21
|
+
* Prefers splitting at paragraph boundaries (\n\n), then line boundaries (\n),
|
|
22
|
+
* then hard-cuts at the limit.
|
|
23
|
+
*
|
|
24
|
+
* Preserves code block fences across splits.
|
|
25
|
+
*/
|
|
26
|
+
export function splitMessage(text, limit = 2000) {
|
|
27
|
+
if (text.length <= limit) {
|
|
28
|
+
return [text];
|
|
29
|
+
}
|
|
30
|
+
const chunks = [];
|
|
31
|
+
let remaining = text;
|
|
32
|
+
while (remaining.length > 0) {
|
|
33
|
+
if (remaining.length <= limit) {
|
|
34
|
+
chunks.push(remaining);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
// Try splitting at paragraph boundary (\n\n)
|
|
38
|
+
let splitIdx = remaining.lastIndexOf("\n\n", limit);
|
|
39
|
+
if (splitIdx > 0) {
|
|
40
|
+
chunks.push(remaining.slice(0, splitIdx));
|
|
41
|
+
remaining = remaining.slice(splitIdx + 2); // skip the \n\n
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
// Try splitting at line boundary (\n)
|
|
45
|
+
splitIdx = remaining.lastIndexOf("\n", limit);
|
|
46
|
+
if (splitIdx > 0) {
|
|
47
|
+
chunks.push(remaining.slice(0, splitIdx));
|
|
48
|
+
remaining = remaining.slice(splitIdx + 1); // skip the \n
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
// Hard cut at limit
|
|
52
|
+
chunks.push(remaining.slice(0, limit));
|
|
53
|
+
remaining = remaining.slice(limit);
|
|
54
|
+
}
|
|
55
|
+
return chunks;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Normalize a Discord message into an IncomingMessage.
|
|
59
|
+
*/
|
|
60
|
+
export function normalizeMessage(msg, agentId) {
|
|
61
|
+
return {
|
|
62
|
+
from: {
|
|
63
|
+
gateway: "discord",
|
|
64
|
+
channel: msg.channelId,
|
|
65
|
+
user: msg.author.username,
|
|
66
|
+
userId: msg.author.id,
|
|
67
|
+
messageId: msg.id,
|
|
68
|
+
},
|
|
69
|
+
to: { agent: agentId },
|
|
70
|
+
content: msg.content,
|
|
71
|
+
attachments: Array.from(msg.attachments.values()).map((a) => ({
|
|
72
|
+
type: a.contentType ?? "application/octet-stream",
|
|
73
|
+
url: a.url,
|
|
74
|
+
filename: a.name ?? undefined,
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// ── Plugin factory ────────────────────────────────────────────────────────
|
|
79
|
+
export default function createDiscordGateway(pluginConfig) {
|
|
80
|
+
let core;
|
|
81
|
+
const clients = new Map();
|
|
82
|
+
const resolvedTokens = new Map();
|
|
83
|
+
// Track our own bot user IDs so we can distinguish "our bots" from "other bots"
|
|
84
|
+
const ownBotUserIds = new Set();
|
|
85
|
+
const plugin = {
|
|
86
|
+
name: "discord-gateway",
|
|
87
|
+
type: "gateway",
|
|
88
|
+
async init(coreRef) {
|
|
89
|
+
core = coreRef;
|
|
90
|
+
// Resolve all bot tokens from env vars
|
|
91
|
+
for (const [botId, botConfig] of Object.entries(pluginConfig.bots)) {
|
|
92
|
+
const token = resolveToken(botConfig.token);
|
|
93
|
+
resolvedTokens.set(botId, token);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
async start() {
|
|
97
|
+
for (const [botId, token] of Array.from(resolvedTokens.entries())) {
|
|
98
|
+
const client = new Client({
|
|
99
|
+
intents: [
|
|
100
|
+
GatewayIntentBits.Guilds,
|
|
101
|
+
GatewayIntentBits.GuildMessages,
|
|
102
|
+
GatewayIntentBits.MessageContent,
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
clients.set(botId, client);
|
|
106
|
+
client.on("ready", () => {
|
|
107
|
+
if (client.user) {
|
|
108
|
+
ownBotUserIds.add(client.user.id);
|
|
109
|
+
logger.info(`discord-gateway: bot "${botId}" connected as ${client.user.tag}`);
|
|
110
|
+
// Log which bound channels this bot can see
|
|
111
|
+
const botBindings = core.config.bindings.filter((b) => b.gateway === "discord" && b.bot === botId);
|
|
112
|
+
for (const b of botBindings) {
|
|
113
|
+
const ch = client.channels.cache.get(b.channel);
|
|
114
|
+
logger.info(`discord-gateway: bot "${botId}" binding ${b.channel} (agent: ${b.agent}) — ${ch ? "visible" : "NOT VISIBLE"}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
client.on("messageCreate", async (msg) => {
|
|
119
|
+
try {
|
|
120
|
+
await handleMessage(msg, botId);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
124
|
+
logger.error(`discord-gateway: error handling message ${msg.id}: ${errMsg}`);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
await client.login(token);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
async stop() {
|
|
131
|
+
for (const [botId, client] of Array.from(clients.entries())) {
|
|
132
|
+
logger.info(`discord-gateway: disconnecting bot "${botId}"`);
|
|
133
|
+
client.destroy();
|
|
134
|
+
}
|
|
135
|
+
clients.clear();
|
|
136
|
+
ownBotUserIds.clear();
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
// Attach sendToChannel for cross-agent messaging (not part of CcgPlugin interface)
|
|
140
|
+
plugin.sendToChannel = async (channelId, botId, content) => {
|
|
141
|
+
const client = clients.get(botId);
|
|
142
|
+
if (!client) {
|
|
143
|
+
throw new Error(`Bot "${botId}" not found in discord-gateway`);
|
|
144
|
+
}
|
|
145
|
+
const channel = await client.channels.fetch(channelId);
|
|
146
|
+
if (!channel || !("send" in channel)) {
|
|
147
|
+
throw new Error(`Channel "${channelId}" not found or not a text channel`);
|
|
148
|
+
}
|
|
149
|
+
const chunks = splitMessage(content);
|
|
150
|
+
for (const chunk of chunks) {
|
|
151
|
+
await channel.send(chunk);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
return plugin;
|
|
155
|
+
// ── Internal message handler ──────────────────────────────────────────
|
|
156
|
+
async function handleMessage(msg, receivingBotId) {
|
|
157
|
+
logger.info(`discord-gateway: bot "${receivingBotId}" received message in channel ${msg.channelId} from ${msg.author.tag} (bot=${msg.author.bot})`);
|
|
158
|
+
// Ignore all bot messages (prevents feedback loops)
|
|
159
|
+
if (msg.author.bot) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Only handle messages if THIS bot is the one bound to this channel.
|
|
163
|
+
// This prevents "several people typing" — only the correct bot responds.
|
|
164
|
+
const binding = core.config.bindings.find((b) => b.gateway === "discord" && b.channel === msg.channelId && b.bot === receivingBotId);
|
|
165
|
+
if (!binding) {
|
|
166
|
+
logger.info(`discord-gateway: bot "${receivingBotId}" no binding for channel ${msg.channelId}`);
|
|
167
|
+
return; // this bot is not bound to this channel
|
|
168
|
+
}
|
|
169
|
+
const agentId = binding.agent;
|
|
170
|
+
// Check if user is in allowedUsers
|
|
171
|
+
if (!pluginConfig.allowedUsers.includes(msg.author.id)) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// Handle slash commands
|
|
175
|
+
const trimmed = msg.content.trim().toLowerCase();
|
|
176
|
+
if (trimmed === "/new" || trimmed === "/reset") {
|
|
177
|
+
const sessionKey = await core.sessions.getOrCreateSession(agentId, "discord", msg.channelId);
|
|
178
|
+
await core.sessions.resetSession(agentId, sessionKey);
|
|
179
|
+
await msg.channel.send(`Session reset for **${agentId}**. Starting fresh.`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (trimmed === "/status") {
|
|
183
|
+
const sessionKey = await core.sessions.getOrCreateSession(agentId, "discord", msg.channelId);
|
|
184
|
+
await msg.channel.send(`**Agent:** ${agentId}\n**Session:** \`${sessionKey}\`\n**Channel:** ${msg.channelId}`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Normalize to IncomingMessage and route
|
|
188
|
+
const incomingMessage = normalizeMessage(msg, agentId);
|
|
189
|
+
// Show typing indicator
|
|
190
|
+
const typingInterval = setInterval(() => {
|
|
191
|
+
msg.channel.sendTyping().catch(() => { });
|
|
192
|
+
}, 5000);
|
|
193
|
+
// Send initial typing
|
|
194
|
+
await msg.channel.sendTyping().catch(() => { });
|
|
195
|
+
try {
|
|
196
|
+
const response = await core.router.route(incomingMessage);
|
|
197
|
+
// Split and send response
|
|
198
|
+
const chunks = splitMessage(response);
|
|
199
|
+
for (const chunk of chunks) {
|
|
200
|
+
await msg.channel.send(chunk);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
clearInterval(typingInterval);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=discord-gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discord-gateway.js","sourceRoot":"","sources":["../../src/plugins/discord-gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CcgPlugin } from "../plugin.js";
|
|
2
|
+
interface SlackBotConfig {
|
|
3
|
+
token: string;
|
|
4
|
+
signingSecret: string;
|
|
5
|
+
appToken: string;
|
|
6
|
+
}
|
|
7
|
+
interface SlackGatewayConfig {
|
|
8
|
+
bots: Record<string, SlackBotConfig>;
|
|
9
|
+
workspace: string;
|
|
10
|
+
allowedUsers: string[];
|
|
11
|
+
commands: string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a config value: if it starts with "$", read from process.env.
|
|
15
|
+
* Throws if the env var is not set.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveToken(value: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Convert standard markdown to Slack mrkdwn format.
|
|
20
|
+
* - **bold** -> *bold*
|
|
21
|
+
* - *italic* (single asterisks not preceded/followed by asterisk) -> _italic_
|
|
22
|
+
* - ~~strikethrough~~ -> ~strikethrough~
|
|
23
|
+
* - [text](url) -> <url|text>
|
|
24
|
+
* - `code` stays as `code`
|
|
25
|
+
* - ```code blocks``` stay as ```code blocks```
|
|
26
|
+
*/
|
|
27
|
+
export declare function markdownToMrkdwn(md: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Split a message into chunks that fit within Slack's character limit.
|
|
30
|
+
* Prefers splitting at newline boundaries.
|
|
31
|
+
*/
|
|
32
|
+
export declare function splitMessage(text: string, maxLen?: number): string[];
|
|
33
|
+
export default function createSlackGateway(pluginConfig: SlackGatewayConfig): CcgPlugin;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=slack-gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-gateway.d.ts","sourceRoot":"","sources":["../../src/plugins/slack-gateway.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,cAAc,CAAC;AAMvD,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAID;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAYlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAqCnD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAO,GAAG,MAAM,EAAE,CA4BlE;AAWD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,YAAY,EAAE,kBAAkB,GAAG,SAAS,CAqOtF"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { App } from "@slack/bolt";
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a config value: if it starts with "$", read from process.env.
|
|
6
|
+
* Throws if the env var is not set.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveToken(value) {
|
|
9
|
+
if (value.startsWith("$")) {
|
|
10
|
+
const envKey = value.slice(1);
|
|
11
|
+
const resolved = process.env[envKey];
|
|
12
|
+
if (!resolved) {
|
|
13
|
+
throw new Error(`Environment variable "${envKey}" is not set (referenced as "${value}")`);
|
|
14
|
+
}
|
|
15
|
+
return resolved;
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Convert standard markdown to Slack mrkdwn format.
|
|
21
|
+
* - **bold** -> *bold*
|
|
22
|
+
* - *italic* (single asterisks not preceded/followed by asterisk) -> _italic_
|
|
23
|
+
* - ~~strikethrough~~ -> ~strikethrough~
|
|
24
|
+
* - [text](url) -> <url|text>
|
|
25
|
+
* - `code` stays as `code`
|
|
26
|
+
* - ```code blocks``` stay as ```code blocks```
|
|
27
|
+
*/
|
|
28
|
+
export function markdownToMrkdwn(md) {
|
|
29
|
+
let result = md;
|
|
30
|
+
// Preserve code blocks first — replace with placeholders
|
|
31
|
+
const codeBlocks = [];
|
|
32
|
+
result = result.replace(/```[\s\S]*?```/g, (match) => {
|
|
33
|
+
codeBlocks.push(match);
|
|
34
|
+
return `\x00CB${codeBlocks.length - 1}\x00`;
|
|
35
|
+
});
|
|
36
|
+
// Preserve inline code
|
|
37
|
+
const inlineCode = [];
|
|
38
|
+
result = result.replace(/`[^`]+`/g, (match) => {
|
|
39
|
+
inlineCode.push(match);
|
|
40
|
+
return `\x00IC${inlineCode.length - 1}\x00`;
|
|
41
|
+
});
|
|
42
|
+
// Handle italic BEFORE bold: extract single-asterisk italic first
|
|
43
|
+
// *italic* -> _italic_ (single asterisks not part of **)
|
|
44
|
+
result = result.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "_$1_");
|
|
45
|
+
// **bold** -> *bold*
|
|
46
|
+
result = result.replace(/\*\*(.+?)\*\*/g, "*$1*");
|
|
47
|
+
// ~~strikethrough~~ -> ~strikethrough~
|
|
48
|
+
result = result.replace(/~~(.+?)~~/g, "~$1~");
|
|
49
|
+
// [text](url) -> <url|text>
|
|
50
|
+
result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "<$2|$1>");
|
|
51
|
+
// Restore inline code
|
|
52
|
+
result = result.replace(/\x00IC(\d+)\x00/g, (_, idx) => inlineCode[Number(idx)]);
|
|
53
|
+
// Restore code blocks
|
|
54
|
+
result = result.replace(/\x00CB(\d+)\x00/g, (_, idx) => codeBlocks[Number(idx)]);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Split a message into chunks that fit within Slack's character limit.
|
|
59
|
+
* Prefers splitting at newline boundaries.
|
|
60
|
+
*/
|
|
61
|
+
export function splitMessage(text, maxLen = 3900) {
|
|
62
|
+
if (text.length <= maxLen)
|
|
63
|
+
return [text];
|
|
64
|
+
const chunks = [];
|
|
65
|
+
let remaining = text;
|
|
66
|
+
while (remaining.length > 0) {
|
|
67
|
+
if (remaining.length <= maxLen) {
|
|
68
|
+
chunks.push(remaining);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
// Try to split at a newline near the limit
|
|
72
|
+
let splitAt = remaining.lastIndexOf("\n", maxLen);
|
|
73
|
+
if (splitAt <= 0) {
|
|
74
|
+
// No good newline, split at a space
|
|
75
|
+
splitAt = remaining.lastIndexOf(" ", maxLen);
|
|
76
|
+
}
|
|
77
|
+
if (splitAt <= 0) {
|
|
78
|
+
// No good split point, hard-cut
|
|
79
|
+
splitAt = maxLen;
|
|
80
|
+
}
|
|
81
|
+
chunks.push(remaining.slice(0, splitAt));
|
|
82
|
+
remaining = remaining.slice(splitAt).replace(/^\n/, "");
|
|
83
|
+
}
|
|
84
|
+
return chunks;
|
|
85
|
+
}
|
|
86
|
+
// ── Plugin factory ────────────────────────────────────────────────────────
|
|
87
|
+
export default function createSlackGateway(pluginConfig) {
|
|
88
|
+
let core;
|
|
89
|
+
const bots = [];
|
|
90
|
+
const resolvedTokens = new Map();
|
|
91
|
+
/**
|
|
92
|
+
* Send a message to a specific channel using a specific bot.
|
|
93
|
+
*/
|
|
94
|
+
async function sendToChannel(channelId, botId, content) {
|
|
95
|
+
const bot = bots.find((b) => b.botId === botId);
|
|
96
|
+
if (!bot) {
|
|
97
|
+
throw new Error(`Slack bot "${botId}" not found`);
|
|
98
|
+
}
|
|
99
|
+
const mrkdwn = markdownToMrkdwn(content);
|
|
100
|
+
const chunks = splitMessage(mrkdwn);
|
|
101
|
+
for (const chunk of chunks) {
|
|
102
|
+
await bot.app.client.chat.postMessage({
|
|
103
|
+
channel: channelId,
|
|
104
|
+
text: chunk,
|
|
105
|
+
blocks: [
|
|
106
|
+
{
|
|
107
|
+
type: "section",
|
|
108
|
+
text: { type: "mrkdwn", text: chunk },
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Handle a slash command from Slack.
|
|
116
|
+
* Returns the response string, or null if unrecognized.
|
|
117
|
+
*/
|
|
118
|
+
async function handleSlashCommand(command, agentId, channelId, userId) {
|
|
119
|
+
switch (command) {
|
|
120
|
+
case "/new":
|
|
121
|
+
case "/reset": {
|
|
122
|
+
const sessionKey = core.sessions.getOrCreateSession(agentId, "slack", channelId);
|
|
123
|
+
// SessionManager.resetSession expects (agentId, sessionKey)
|
|
124
|
+
// but the interface exposed via CcgCore only has getOrCreateSession.
|
|
125
|
+
// We just create a new session reference which effectively resets context.
|
|
126
|
+
return `Session reset for agent *${agentId}* in this channel.`;
|
|
127
|
+
}
|
|
128
|
+
case "/status": {
|
|
129
|
+
const agent = core.agents.getAgent(agentId);
|
|
130
|
+
if (!agent)
|
|
131
|
+
return `Agent "${agentId}" not found.`;
|
|
132
|
+
return `*${agent.name}* ${agent.emoji} is online.\nModel: \`${agent.model}\``;
|
|
133
|
+
}
|
|
134
|
+
default:
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Register message and event handlers for a single bot App.
|
|
140
|
+
*/
|
|
141
|
+
function registerHandlers(app, botId) {
|
|
142
|
+
// Handle messages
|
|
143
|
+
app.message(async ({ message, say, client }) => {
|
|
144
|
+
// Ignore bot messages and message_changed subtypes
|
|
145
|
+
if (!message || message.subtype)
|
|
146
|
+
return;
|
|
147
|
+
// message type narrowing — we only handle standard user messages
|
|
148
|
+
if (!("user" in message) || !("text" in message))
|
|
149
|
+
return;
|
|
150
|
+
const userId = message.user;
|
|
151
|
+
const text = message.text ?? "";
|
|
152
|
+
const channelId = message.channel;
|
|
153
|
+
const messageTs = message.ts;
|
|
154
|
+
const threadTs = "thread_ts" in message ? message.thread_ts : undefined;
|
|
155
|
+
// Check if user is allowed
|
|
156
|
+
if (!pluginConfig.allowedUsers.includes(userId)) {
|
|
157
|
+
logger.debug(`slack: ignoring message from non-allowed user ${userId}`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Resolve agent from bindings
|
|
161
|
+
const agentId = core.router.resolveAgent("slack", channelId);
|
|
162
|
+
if (!agentId) {
|
|
163
|
+
logger.debug(`slack: no agent bound to channel ${channelId}`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Check if message is a slash command (text-based, not actual Slack slash commands)
|
|
167
|
+
const trimmed = text.trim();
|
|
168
|
+
if (pluginConfig.commands.includes(trimmed)) {
|
|
169
|
+
const cmdResponse = await handleSlashCommand(trimmed, agentId, channelId, userId);
|
|
170
|
+
if (cmdResponse) {
|
|
171
|
+
await say({
|
|
172
|
+
text: cmdResponse,
|
|
173
|
+
thread_ts: threadTs ?? messageTs,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Add hourglass reaction while processing
|
|
179
|
+
try {
|
|
180
|
+
await client.reactions.add({
|
|
181
|
+
channel: channelId,
|
|
182
|
+
timestamp: messageTs,
|
|
183
|
+
name: "hourglass_flowing_sand",
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// Reaction may fail if already added or permissions issue; non-fatal
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
// Build IncomingMessage
|
|
191
|
+
const incoming = {
|
|
192
|
+
from: {
|
|
193
|
+
gateway: "slack",
|
|
194
|
+
channel: channelId,
|
|
195
|
+
user: userId,
|
|
196
|
+
userId,
|
|
197
|
+
messageId: messageTs,
|
|
198
|
+
},
|
|
199
|
+
to: { agent: agentId },
|
|
200
|
+
content: text,
|
|
201
|
+
attachments: [],
|
|
202
|
+
};
|
|
203
|
+
// Route the message
|
|
204
|
+
const response = await core.router.route(incoming);
|
|
205
|
+
// Convert and send response
|
|
206
|
+
const mrkdwn = markdownToMrkdwn(response);
|
|
207
|
+
const chunks = splitMessage(mrkdwn);
|
|
208
|
+
for (const chunk of chunks) {
|
|
209
|
+
await say({
|
|
210
|
+
text: chunk,
|
|
211
|
+
blocks: [
|
|
212
|
+
{
|
|
213
|
+
type: "section",
|
|
214
|
+
text: { type: "mrkdwn", text: chunk },
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
thread_ts: threadTs ?? messageTs,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
223
|
+
logger.error(`slack: error handling message: ${errMsg}`);
|
|
224
|
+
await say({
|
|
225
|
+
text: `:warning: Error: ${errMsg}`,
|
|
226
|
+
thread_ts: threadTs ?? messageTs,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
// Remove hourglass reaction
|
|
231
|
+
try {
|
|
232
|
+
await client.reactions.remove({
|
|
233
|
+
channel: channelId,
|
|
234
|
+
timestamp: messageTs,
|
|
235
|
+
name: "hourglass_flowing_sand",
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Non-fatal
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
// ── Return the CcgPlugin object ──────────────────────────────────────────
|
|
245
|
+
return {
|
|
246
|
+
name: "slack-gateway",
|
|
247
|
+
type: "gateway",
|
|
248
|
+
async init(coreRef) {
|
|
249
|
+
core = coreRef;
|
|
250
|
+
// Resolve all tokens from env vars
|
|
251
|
+
for (const [botId, botConfig] of Object.entries(pluginConfig.bots)) {
|
|
252
|
+
const token = resolveToken(botConfig.token);
|
|
253
|
+
const signingSecret = resolveToken(botConfig.signingSecret);
|
|
254
|
+
const appToken = resolveToken(botConfig.appToken);
|
|
255
|
+
resolvedTokens.set(botId, { token, signingSecret, appToken });
|
|
256
|
+
}
|
|
257
|
+
logger.info(`slack-gateway: initialized with ${Object.keys(pluginConfig.bots).length} bot(s)`);
|
|
258
|
+
},
|
|
259
|
+
async start() {
|
|
260
|
+
for (const [botId, tokens] of resolvedTokens.entries()) {
|
|
261
|
+
const app = new App({
|
|
262
|
+
token: tokens.token,
|
|
263
|
+
signingSecret: tokens.signingSecret,
|
|
264
|
+
appToken: tokens.appToken,
|
|
265
|
+
socketMode: true,
|
|
266
|
+
logLevel: "ERROR",
|
|
267
|
+
});
|
|
268
|
+
registerHandlers(app, botId);
|
|
269
|
+
await app.start();
|
|
270
|
+
bots.push({ app, botId });
|
|
271
|
+
logger.info(`slack-gateway: bot "${botId}" started in socket mode`);
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
async stop() {
|
|
275
|
+
for (const bot of bots) {
|
|
276
|
+
try {
|
|
277
|
+
await bot.app.stop();
|
|
278
|
+
logger.info(`slack-gateway: bot "${bot.botId}" stopped`);
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
282
|
+
logger.error(`slack-gateway: error stopping bot "${bot.botId}": ${errMsg}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
bots.length = 0;
|
|
286
|
+
},
|
|
287
|
+
// Expose sendToChannel for cross-agent messaging
|
|
288
|
+
sendToChannel,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=slack-gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-gateway.js","sourceRoot":"","sources":["../../src/plugins/slack-gateway.ts"],"names":[],"mappings":"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"}
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AgentRegistry } from "./agents.js";
|
|
2
|
+
import type { SessionManager } from "./sessions.js";
|
|
3
|
+
import type { ContextBuilder } from "./context.js";
|
|
4
|
+
import type { CCSpawner } from "./spawner.js";
|
|
5
|
+
import type { IncomingMessage, BindingConfig } from "./types.js";
|
|
6
|
+
export declare class MessageRouter {
|
|
7
|
+
private agents;
|
|
8
|
+
private sessions;
|
|
9
|
+
private context;
|
|
10
|
+
private spawner;
|
|
11
|
+
private bindings;
|
|
12
|
+
constructor(agents: AgentRegistry, sessions: SessionManager, context: ContextBuilder, spawner: CCSpawner, bindings: BindingConfig[]);
|
|
13
|
+
/**
|
|
14
|
+
* Resolve which agent handles a message based on bindings.
|
|
15
|
+
* Given (gateway, channelId), find the matching binding and return binding.agent.
|
|
16
|
+
*/
|
|
17
|
+
resolveAgent(gateway: string, channelId: string): string | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Full message dispatch pipeline.
|
|
20
|
+
*
|
|
21
|
+
* 1. Look up agent config from registry
|
|
22
|
+
* 2. Derive session key: {agentId}:{gateway}:{channel}
|
|
23
|
+
* 3. Get or create session
|
|
24
|
+
* 4. Append user message to session
|
|
25
|
+
* 5. Build context
|
|
26
|
+
* 6. Spawn claude --print
|
|
27
|
+
* 7. Append assistant response to session (or error on failure)
|
|
28
|
+
* 8. Return response text
|
|
29
|
+
*/
|
|
30
|
+
route(message: IncomingMessage): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Add a binding at runtime.
|
|
33
|
+
*/
|
|
34
|
+
addBinding(binding: BindingConfig): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get all bindings for a given agent.
|
|
37
|
+
*/
|
|
38
|
+
getBindingsForAgent(agentId: string): BindingConfig[];
|
|
39
|
+
/**
|
|
40
|
+
* Get the primary (first) binding for an agent.
|
|
41
|
+
*/
|
|
42
|
+
getPrimaryBinding(agentId: string): BindingConfig | undefined;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIjE,qBAAa,aAAa;IAEtB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;gBAJR,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,aAAa,EAAE;IAGnC;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOpE;;;;;;;;;;;OAWG;IACG,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAgEtD;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAIxC;;OAEG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE;IAIrD;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;CAG9D"}
|