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.
Files changed (75) hide show
  1. package/README.md +252 -0
  2. package/bin/ccg-dev.sh +3 -0
  3. package/dist/agents.d.ts +17 -0
  4. package/dist/agents.d.ts.map +1 -0
  5. package/dist/agents.js +45 -0
  6. package/dist/agents.js.map +1 -0
  7. package/dist/chat.d.ts +14 -0
  8. package/dist/chat.d.ts.map +1 -0
  9. package/dist/chat.js +104 -0
  10. package/dist/chat.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +501 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config.d.ts +53 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +70 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/context.d.ts +45 -0
  20. package/dist/context.d.ts.map +1 -0
  21. package/dist/context.js +201 -0
  22. package/dist/context.js.map +1 -0
  23. package/dist/daemon.d.ts +27 -0
  24. package/dist/daemon.d.ts.map +1 -0
  25. package/dist/daemon.js +207 -0
  26. package/dist/daemon.js.map +1 -0
  27. package/dist/heartbeat.d.ts +42 -0
  28. package/dist/heartbeat.d.ts.map +1 -0
  29. package/dist/heartbeat.js +153 -0
  30. package/dist/heartbeat.js.map +1 -0
  31. package/dist/logger.d.ts +15 -0
  32. package/dist/logger.d.ts.map +1 -0
  33. package/dist/logger.js +70 -0
  34. package/dist/logger.js.map +1 -0
  35. package/dist/messaging.d.ts +43 -0
  36. package/dist/messaging.d.ts.map +1 -0
  37. package/dist/messaging.js +132 -0
  38. package/dist/messaging.js.map +1 -0
  39. package/dist/migrate.d.ts +24 -0
  40. package/dist/migrate.d.ts.map +1 -0
  41. package/dist/migrate.js +356 -0
  42. package/dist/migrate.js.map +1 -0
  43. package/dist/plugin.d.ts +63 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +93 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/plugins/discord-gateway.d.ts +32 -0
  48. package/dist/plugins/discord-gateway.d.ts.map +1 -0
  49. package/dist/plugins/discord-gateway.js +208 -0
  50. package/dist/plugins/discord-gateway.js.map +1 -0
  51. package/dist/plugins/slack-gateway.d.ts +35 -0
  52. package/dist/plugins/slack-gateway.d.ts.map +1 -0
  53. package/dist/plugins/slack-gateway.js +291 -0
  54. package/dist/plugins/slack-gateway.js.map +1 -0
  55. package/dist/router.d.ts +44 -0
  56. package/dist/router.d.ts.map +1 -0
  57. package/dist/router.js +103 -0
  58. package/dist/router.js.map +1 -0
  59. package/dist/sessions.d.ts +55 -0
  60. package/dist/sessions.d.ts.map +1 -0
  61. package/dist/sessions.js +160 -0
  62. package/dist/sessions.js.map +1 -0
  63. package/dist/skills.d.ts +58 -0
  64. package/dist/skills.d.ts.map +1 -0
  65. package/dist/skills.js +194 -0
  66. package/dist/skills.js.map +1 -0
  67. package/dist/spawner.d.ts +29 -0
  68. package/dist/spawner.d.ts.map +1 -0
  69. package/dist/spawner.js +54 -0
  70. package/dist/spawner.js.map +1 -0
  71. package/dist/types.d.ts +22 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +4 -0
  74. package/dist/types.js.map +1 -0
  75. package/package.json +48 -0
@@ -0,0 +1,356 @@
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { homedir } from 'node:os';
5
+ import { saveConfig, ensureDirectories, getCcgHome } from './config.js';
6
+ // ── Migration ───────────────────────────────────────────────────────────────
7
+ const DEFAULT_ALLOWED_TOOLS = ['Edit', 'Read', 'Write', 'Bash', 'Grep', 'Glob'];
8
+ /**
9
+ * Strip provider prefix from a model name.
10
+ * e.g. "anthropic/claude-opus-4-6" -> "claude-opus-4-6"
11
+ */
12
+ export function stripModelPrefix(model) {
13
+ const slashIndex = model.indexOf('/');
14
+ if (slashIndex === -1)
15
+ return model;
16
+ return model.slice(slashIndex + 1);
17
+ }
18
+ /**
19
+ * Generate a Discord bot token env var name.
20
+ * e.g. "ginger" -> "DISCORD_GINGER_TOKEN"
21
+ */
22
+ export function botTokenEnvVar(accountName) {
23
+ return `DISCORD_${accountName.toUpperCase()}_TOKEN`;
24
+ }
25
+ /**
26
+ * Migrate from OpenClaw configuration to ccgateway config.
27
+ */
28
+ export async function migrateFromOpenClaw(options = {}) {
29
+ // 1. Find openclaw.json
30
+ const configFile = options.configPath || join(homedir(), '.openclaw', 'openclaw.json');
31
+ if (!existsSync(configFile)) {
32
+ throw new Error(`OpenClaw config not found at: ${configFile}\n` +
33
+ `Specify the path with: ccg migrate openclaw --config <path>`);
34
+ }
35
+ // 2. Read and parse
36
+ const raw = await readFile(configFile, 'utf-8');
37
+ const ocConfig = JSON.parse(raw);
38
+ // 3. Extract agents
39
+ const agents = extractAgents(ocConfig);
40
+ // 4. Extract bindings
41
+ const bindings = extractBindings(ocConfig, agents);
42
+ // 5. Extract bot tokens + generate .env and plugin config
43
+ const { envLines, pluginBots, instructions: tokenInstructions } = extractBotTokens(ocConfig);
44
+ // 6. Extract guild ID for Discord plugin config
45
+ const guildId = extractGuildId(ocConfig);
46
+ // 7. Build Discord gateway plugin entry if we have bots
47
+ const plugins = [];
48
+ if (Object.keys(pluginBots).length > 0) {
49
+ plugins.push({
50
+ name: 'discord-gateway',
51
+ enabled: true,
52
+ config: {
53
+ bots: pluginBots,
54
+ guild: guildId || '',
55
+ allowedUsers: extractAllowedUsers(ocConfig),
56
+ commands: ['/new', '/reset', '/status'],
57
+ },
58
+ });
59
+ }
60
+ // 8. Extract heartbeats from cron/jobs.json
61
+ const cronPath = join(options.configPath
62
+ ? join(options.configPath, '..', 'cron', 'jobs.json')
63
+ : join(homedir(), '.openclaw', 'cron', 'jobs.json'));
64
+ const heartbeats = await extractHeartbeats(cronPath);
65
+ // 9. Build ccgateway config
66
+ const ccgConfig = {
67
+ agents,
68
+ bindings,
69
+ plugins,
70
+ heartbeats,
71
+ };
72
+ // 10. Print summary
73
+ console.log('--- OpenClaw Migration Summary ---');
74
+ console.log(` Agents: ${agents.length}`);
75
+ console.log(` Bindings: ${bindings.length}`);
76
+ console.log(` Plugins: ${plugins.length}`);
77
+ console.log(` Heartbeats: ${heartbeats.length}`);
78
+ console.log();
79
+ if (agents.length > 0) {
80
+ console.log('Agents:');
81
+ for (const a of agents) {
82
+ console.log(` ${a.emoji || '-'} ${a.id} (${a.name}) — model: ${a.model}, workspace: ${a.workspace}`);
83
+ }
84
+ console.log();
85
+ }
86
+ if (bindings.length > 0) {
87
+ console.log('Bindings:');
88
+ for (const b of bindings) {
89
+ console.log(` ${b.agent} <- ${b.gateway}:${b.channel} (bot: ${b.bot})`);
90
+ }
91
+ console.log();
92
+ }
93
+ if (plugins.length > 0) {
94
+ console.log('Plugins:');
95
+ for (const p of plugins) {
96
+ console.log(` ${p.name} (${p.enabled ? 'enabled' : 'disabled'})`);
97
+ }
98
+ console.log();
99
+ }
100
+ if (heartbeats.length > 0) {
101
+ console.log('Heartbeats:');
102
+ for (const h of heartbeats) {
103
+ console.log(` ${h.agent}: ${h.cron} (${h.tz})`);
104
+ }
105
+ console.log();
106
+ }
107
+ if (envLines.length > 0) {
108
+ console.log(`Bot tokens found: ${envLines.length}`);
109
+ for (const line of tokenInstructions) {
110
+ console.log(line);
111
+ }
112
+ console.log();
113
+ }
114
+ // 11. Dry run check
115
+ if (options.dryRun) {
116
+ console.log('[dry-run] No files were written.');
117
+ return;
118
+ }
119
+ // 12. Save config, .env, and ensure directories
120
+ await ensureDirectories();
121
+ await saveConfig(ccgConfig);
122
+ const home = getCcgHome();
123
+ // Write .env with actual bot tokens
124
+ if (envLines.length > 0) {
125
+ const envPath = join(home, '.env');
126
+ await writeFile(envPath, envLines.join('\n') + '\n', 'utf-8');
127
+ console.log(`Bot tokens written to: ${envPath}`);
128
+ }
129
+ console.log(`Config written to: ${join(home, 'config.json')}`);
130
+ console.log();
131
+ console.log('To start ccgateway, load the .env first:');
132
+ console.log(` source ${join(home, '.env')} && ccg start`);
133
+ console.log();
134
+ console.log('Migration complete.');
135
+ }
136
+ // ── Extraction helpers ──────────────────────────────────────────────────────
137
+ function extractAgents(config) {
138
+ const list = config.agents?.list;
139
+ if (!list || list.length === 0)
140
+ return [];
141
+ const defaults = config.agents?.defaults;
142
+ const defaultModel = defaults?.model?.primary || 'claude-sonnet-4-6';
143
+ const defaultWorkspace = defaults?.workspace || homedir();
144
+ const defaultMaxConcurrent = defaults?.maxConcurrent || 4;
145
+ return list.map((agent) => {
146
+ // Determine model: agent-level override or default
147
+ const rawModel = agent.model?.primary || defaultModel;
148
+ const model = stripModelPrefix(rawModel);
149
+ // Determine workspace: agent-level override or default
150
+ const workspace = agent.workspace || defaultWorkspace;
151
+ // Agent name: identity.name or the agent id
152
+ const name = agent.identity?.name || agent.name || agent.id;
153
+ // Emoji
154
+ const emoji = agent.identity?.emoji || '';
155
+ return {
156
+ id: agent.id,
157
+ name,
158
+ emoji,
159
+ workspace,
160
+ model,
161
+ skills: [],
162
+ allowedTools: [...DEFAULT_ALLOWED_TOOLS],
163
+ maxConcurrentSessions: defaultMaxConcurrent,
164
+ };
165
+ });
166
+ }
167
+ function extractBindings(config, agents) {
168
+ const bindings = [];
169
+ const seen = new Set();
170
+ // 1. Extract from explicit bindings array
171
+ const ocBindings = config.bindings;
172
+ if (ocBindings) {
173
+ for (const binding of ocBindings) {
174
+ const key = `${binding.match.channel}:${binding.match.peer.id}:${binding.match.accountId}`;
175
+ if (!seen.has(key)) {
176
+ seen.add(key);
177
+ bindings.push({
178
+ agent: binding.agentId,
179
+ gateway: binding.match.channel,
180
+ channel: binding.match.peer.id,
181
+ bot: binding.match.accountId,
182
+ });
183
+ }
184
+ }
185
+ }
186
+ // 2. Extract from channels.discord.accounts.{bot}.guilds.{guild}.channels
187
+ // This catches channels that aren't in the bindings array
188
+ const accounts = config.channels?.discord?.accounts;
189
+ if (accounts) {
190
+ // Build a map of bot → agent (first matching agent for each bot)
191
+ const botToAgent = new Map();
192
+ for (const agent of agents) {
193
+ // Check if any existing binding maps this bot to an agent
194
+ const existing = bindings.find((b) => b.bot === agent.id);
195
+ if (existing) {
196
+ botToAgent.set(agent.id, existing.agent);
197
+ }
198
+ }
199
+ // Also check explicit bindings for bot→agent mapping
200
+ if (ocBindings) {
201
+ for (const b of ocBindings) {
202
+ botToAgent.set(b.match.accountId, b.agentId);
203
+ }
204
+ }
205
+ for (const [botName, acct] of Object.entries(accounts)) {
206
+ const guilds = acct.guilds;
207
+ if (!guilds)
208
+ continue;
209
+ const agentId = botToAgent.get(botName);
210
+ if (!agentId)
211
+ continue;
212
+ for (const guild of Object.values(guilds)) {
213
+ const channels = guild.channels;
214
+ if (!channels)
215
+ continue;
216
+ for (const [chId, chConf] of Object.entries(channels)) {
217
+ if (!chConf.enabled)
218
+ continue;
219
+ const key = `discord:${chId}:${botName}`;
220
+ if (!seen.has(key)) {
221
+ seen.add(key);
222
+ bindings.push({
223
+ agent: agentId,
224
+ gateway: 'discord',
225
+ channel: chId,
226
+ bot: botName,
227
+ });
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ return bindings;
234
+ }
235
+ function extractBotTokens(config) {
236
+ const accounts = config.channels?.discord?.accounts;
237
+ if (!accounts)
238
+ return { envLines: [], pluginBots: {}, instructions: [] };
239
+ const envLines = [];
240
+ const pluginBots = {};
241
+ const instructions = [];
242
+ for (const [name, account] of Object.entries(accounts)) {
243
+ const envVar = botTokenEnvVar(name);
244
+ if (account.token) {
245
+ envLines.push(`export ${envVar}=${account.token}`);
246
+ pluginBots[name] = { token: `$${envVar}` };
247
+ instructions.push(` ${envVar} → ${name} bot`);
248
+ }
249
+ }
250
+ return { envLines, pluginBots, instructions };
251
+ }
252
+ function extractGuildId(config) {
253
+ const accounts = config.channels?.discord?.accounts;
254
+ if (!accounts)
255
+ return undefined;
256
+ // Take the first guild ID found across any account
257
+ for (const account of Object.values(accounts)) {
258
+ const guilds = account.guilds;
259
+ if (guilds) {
260
+ const firstGuildId = Object.keys(guilds)[0];
261
+ if (firstGuildId)
262
+ return firstGuildId;
263
+ }
264
+ }
265
+ return undefined;
266
+ }
267
+ function extractAllowedUsers(config) {
268
+ const accounts = config.channels?.discord?.accounts;
269
+ if (!accounts)
270
+ return [];
271
+ // Collect unique user IDs from all guild user lists
272
+ const users = new Set();
273
+ for (const account of Object.values(accounts)) {
274
+ const guilds = account.guilds;
275
+ if (guilds) {
276
+ for (const guild of Object.values(guilds)) {
277
+ const guildUsers = guild.users;
278
+ if (guildUsers) {
279
+ for (const u of guildUsers)
280
+ users.add(u);
281
+ }
282
+ }
283
+ }
284
+ }
285
+ return [...users];
286
+ }
287
+ async function extractHeartbeats(cronPath) {
288
+ if (!existsSync(cronPath))
289
+ return [];
290
+ try {
291
+ const raw = await readFile(cronPath, 'utf-8');
292
+ const data = JSON.parse(raw);
293
+ const jobs = data.jobs;
294
+ if (!jobs || jobs.length === 0)
295
+ return [];
296
+ // Only extract enabled cron-type jobs (not one-shot "at" jobs)
297
+ return jobs
298
+ .filter((job) => job.enabled && job.schedule.kind === 'cron' && job.schedule.expr)
299
+ .map((job) => ({
300
+ agent: job.agentId,
301
+ cron: job.schedule.expr,
302
+ tz: job.schedule.tz || 'UTC',
303
+ }));
304
+ }
305
+ catch {
306
+ return [];
307
+ }
308
+ }
309
+ // ── Init ────────────────────────────────────────────────────────────────────
310
+ /**
311
+ * Interactive setup for new users (no OpenClaw).
312
+ * Creates the ~/.ccgateway/ structure with a minimal starter config.
313
+ */
314
+ export async function initNew() {
315
+ const { createInterface } = await import('node:readline');
316
+ const rl = createInterface({
317
+ input: process.stdin,
318
+ output: process.stdout,
319
+ });
320
+ const ask = (question) => new Promise((resolve) => {
321
+ rl.question(question, (answer) => resolve(answer.trim()));
322
+ });
323
+ console.log('--- ccgateway init ---');
324
+ console.log('Setting up a new ccgateway configuration.\n');
325
+ const agentName = (await ask('First agent name [assistant]: ')) || 'assistant';
326
+ const agentId = agentName.toLowerCase().replace(/\s+/g, '-');
327
+ const workspace = (await ask(`Workspace directory [${process.cwd()}]: `)) || process.cwd();
328
+ const model = (await ask('Model [claude-sonnet-4-6]: ')) || 'claude-sonnet-4-6';
329
+ rl.close();
330
+ const config = {
331
+ agents: [
332
+ {
333
+ id: agentId,
334
+ name: agentName,
335
+ emoji: '',
336
+ workspace,
337
+ model,
338
+ skills: [],
339
+ allowedTools: [...DEFAULT_ALLOWED_TOOLS],
340
+ maxConcurrentSessions: 4,
341
+ },
342
+ ],
343
+ bindings: [],
344
+ plugins: [],
345
+ heartbeats: [],
346
+ };
347
+ await ensureDirectories();
348
+ await saveConfig(config);
349
+ console.log(`\nccgateway initialized at: ${process.env.CCG_HOME || join(homedir(), '.ccgateway')}`);
350
+ console.log(`Agent "${agentId}" created with workspace: ${workspace}`);
351
+ console.log('\nNext steps:');
352
+ console.log(' ccg agents list — see your agents');
353
+ console.log(' ccg chat <agent> — start a chat');
354
+ console.log(' ccg start — start the daemon');
355
+ }
356
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { CcgConfig, AgentConfig, IncomingMessage } from "./types.js";
2
+ export interface AgentRegistry {
3
+ getAgent(id: string): AgentConfig | undefined;
4
+ listAgents(): AgentConfig[];
5
+ }
6
+ export interface SessionManager {
7
+ getOrCreateSession(agentId: string, source: string, sourceId: string): string;
8
+ resetSession(agentId: string, sessionKey: string): Promise<void>;
9
+ }
10
+ export interface MessageRouter {
11
+ route(message: IncomingMessage): Promise<string>;
12
+ resolveAgent(gateway: string, channelId: string): string | undefined;
13
+ }
14
+ export interface CcgCore {
15
+ config: CcgConfig;
16
+ agents: AgentRegistry;
17
+ sessions: SessionManager;
18
+ router: MessageRouter;
19
+ send(agentId: string, message: string, fromAgent?: string): Promise<void>;
20
+ }
21
+ export type PluginType = "gateway" | "skill" | "tool";
22
+ export interface CcgPlugin {
23
+ name: string;
24
+ type: PluginType;
25
+ init(core: CcgCore): Promise<void>;
26
+ start?(): Promise<void>;
27
+ stop?(): Promise<void>;
28
+ }
29
+ /** A module's default export must be a factory that returns a CcgPlugin. */
30
+ export type PluginFactory = () => CcgPlugin;
31
+ export declare class PluginLoader {
32
+ private plugins;
33
+ /**
34
+ * Loads all enabled plugins listed in `config.plugins`.
35
+ *
36
+ * For each entry the loader tries, in order:
37
+ * 1. `import(name)` — works for packages in node_modules
38
+ * 2. `import($CCG_HOME/plugins/<name>/index.js)`
39
+ *
40
+ * The module's default export must be a `PluginFactory` (a function
41
+ * returning a `CcgPlugin`).
42
+ */
43
+ loadPlugins(config: CcgConfig, core: CcgCore): Promise<void>;
44
+ /** Start all loaded plugins (in load order). */
45
+ startAll(): Promise<void>;
46
+ /** Stop all loaded plugins (reverse of load order). */
47
+ stopAll(): Promise<void>;
48
+ /** Register a plugin that was created externally (e.g., built-in plugins). */
49
+ registerPlugin(plugin: CcgPlugin): void;
50
+ /** Returns all loaded plugins. */
51
+ getPlugins(): CcgPlugin[];
52
+ /** Returns loaded plugins filtered by type. */
53
+ getPluginsByType(type: PluginType): CcgPlugin[];
54
+ /** Returns a specific plugin by name, or undefined. */
55
+ getPlugin(name: string): CcgPlugin | undefined;
56
+ /**
57
+ * Attempt to import a plugin module.
58
+ * Tries the bare name first (node_modules), then falls back to
59
+ * `$CCG_HOME/plugins/<name>/index.js`.
60
+ */
61
+ private importPlugin;
62
+ }
63
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,eAAe,EAChB,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAC9C,UAAU,IAAI,WAAW,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC;IACV,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACtE;AAID,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAID,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,4EAA4E;AAC5E,MAAM,MAAM,aAAa,GAAG,MAAM,SAAS,CAAC;AAI5C,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAmB;IAElC;;;;;;;;;OASG;IACG,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAkClE,gDAAgD;IAC1C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B,uDAAuD;IACjD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B,8EAA8E;IAC9E,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAIvC,kCAAkC;IAClC,UAAU,IAAI,SAAS,EAAE;IAIzB,+CAA+C;IAC/C,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE;IAI/C,uDAAuD;IACvD,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAM9C;;;;OAIG;YACW,YAAY;CAW3B"}
package/dist/plugin.js ADDED
@@ -0,0 +1,93 @@
1
+ import { join } from "node:path";
2
+ import { getCcgHome } from "./config.js";
3
+ import { logger } from "./logger.js";
4
+ // ── Plugin loader ──────────────────────────────────────────────────────────
5
+ export class PluginLoader {
6
+ plugins = [];
7
+ /**
8
+ * Loads all enabled plugins listed in `config.plugins`.
9
+ *
10
+ * For each entry the loader tries, in order:
11
+ * 1. `import(name)` — works for packages in node_modules
12
+ * 2. `import($CCG_HOME/plugins/<name>/index.js)`
13
+ *
14
+ * The module's default export must be a `PluginFactory` (a function
15
+ * returning a `CcgPlugin`).
16
+ */
17
+ async loadPlugins(config, core) {
18
+ for (const entry of config.plugins) {
19
+ if (!entry.enabled) {
20
+ logger.debug(`plugin: skipping disabled plugin "${entry.name}"`);
21
+ continue;
22
+ }
23
+ let mod;
24
+ try {
25
+ mod = await this.importPlugin(entry.name);
26
+ }
27
+ catch (err) {
28
+ const message = err instanceof Error ? err.message : String(err);
29
+ logger.error(`plugin: failed to import "${entry.name}": ${message}`);
30
+ throw new Error(`Failed to load plugin "${entry.name}": ${message}`);
31
+ }
32
+ if (typeof mod.default !== "function") {
33
+ throw new Error(`Plugin "${entry.name}" does not default-export a factory function`);
34
+ }
35
+ const plugin = mod.default();
36
+ await plugin.init(core);
37
+ this.plugins.push(plugin);
38
+ logger.info(`plugin: loaded "${plugin.name}" (type=${plugin.type})`);
39
+ }
40
+ }
41
+ /** Start all loaded plugins (in load order). */
42
+ async startAll() {
43
+ for (const plugin of this.plugins) {
44
+ if (plugin.start) {
45
+ await plugin.start();
46
+ logger.info(`plugin: started "${plugin.name}"`);
47
+ }
48
+ }
49
+ }
50
+ /** Stop all loaded plugins (reverse of load order). */
51
+ async stopAll() {
52
+ for (let i = this.plugins.length - 1; i >= 0; i--) {
53
+ const plugin = this.plugins[i];
54
+ if (plugin.stop) {
55
+ await plugin.stop();
56
+ logger.info(`plugin: stopped "${plugin.name}"`);
57
+ }
58
+ }
59
+ }
60
+ /** Register a plugin that was created externally (e.g., built-in plugins). */
61
+ registerPlugin(plugin) {
62
+ this.plugins.push(plugin);
63
+ }
64
+ /** Returns all loaded plugins. */
65
+ getPlugins() {
66
+ return [...this.plugins];
67
+ }
68
+ /** Returns loaded plugins filtered by type. */
69
+ getPluginsByType(type) {
70
+ return this.plugins.filter((p) => p.type === type);
71
+ }
72
+ /** Returns a specific plugin by name, or undefined. */
73
+ getPlugin(name) {
74
+ return this.plugins.find((p) => p.name === name);
75
+ }
76
+ // ── Private helpers ────────────────────────────────────────────────────
77
+ /**
78
+ * Attempt to import a plugin module.
79
+ * Tries the bare name first (node_modules), then falls back to
80
+ * `$CCG_HOME/plugins/<name>/index.js`.
81
+ */
82
+ async importPlugin(name) {
83
+ try {
84
+ return await import(name);
85
+ }
86
+ catch {
87
+ // Fall back to the local plugins directory
88
+ const localPath = join(getCcgHome(), "plugins", name, "index.js");
89
+ return await import(localPath);
90
+ }
91
+ }
92
+ }
93
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type Message } from "discord.js";
2
+ import type { CcgPlugin } from "../plugin.js";
3
+ import type { IncomingMessage } from "../types.js";
4
+ interface DiscordBotConfig {
5
+ token: string;
6
+ }
7
+ interface DiscordGatewayConfig {
8
+ bots: Record<string, DiscordBotConfig>;
9
+ guild: string;
10
+ allowedUsers: string[];
11
+ commands: string[];
12
+ }
13
+ /**
14
+ * Resolve a token value. If it starts with "$", treat it as an env var name.
15
+ * Throws if the env var is not set.
16
+ */
17
+ export declare function resolveToken(token: string): string;
18
+ /**
19
+ * Smart message splitter for Discord's 2000-char limit.
20
+ * Prefers splitting at paragraph boundaries (\n\n), then line boundaries (\n),
21
+ * then hard-cuts at the limit.
22
+ *
23
+ * Preserves code block fences across splits.
24
+ */
25
+ export declare function splitMessage(text: string, limit?: number): string[];
26
+ /**
27
+ * Normalize a Discord message into an IncomingMessage.
28
+ */
29
+ export declare function normalizeMessage(msg: Message, agentId: string): IncomingMessage;
30
+ export default function createDiscordGateway(pluginConfig: DiscordGatewayConfig): CcgPlugin;
31
+ export {};
32
+ //# sourceMappingURL=discord-gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord-gateway.d.ts","sourceRoot":"","sources":["../../src/plugins/discord-gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,OAAO,EAAoB,MAAM,YAAY,CAAC;AACvF,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAKnD,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,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;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,GAAG,MAAM,EAAE,CAoCzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,GACd,eAAe,CAiBjB;AAID,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAC1C,YAAY,EAAE,oBAAoB,GACjC,SAAS,CAyLX"}