agent4discord 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 (78) hide show
  1. package/README.ko.md +134 -0
  2. package/README.md +170 -0
  3. package/dist/bot.d.ts +1 -0
  4. package/dist/bot.js +114 -0
  5. package/dist/bot.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +27 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/index.d.ts +9 -0
  10. package/dist/commands/index.js +44 -0
  11. package/dist/commands/index.js.map +1 -0
  12. package/dist/commands/init.d.ts +5 -0
  13. package/dist/commands/init.js +152 -0
  14. package/dist/commands/init.js.map +1 -0
  15. package/dist/commands/model.d.ts +5 -0
  16. package/dist/commands/model.js +65 -0
  17. package/dist/commands/model.js.map +1 -0
  18. package/dist/commands/resume.d.ts +6 -0
  19. package/dist/commands/resume.js +113 -0
  20. package/dist/commands/resume.js.map +1 -0
  21. package/dist/config.d.ts +12 -0
  22. package/dist/config.js +49 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/formatters/chunker.d.ts +5 -0
  25. package/dist/formatters/chunker.js +46 -0
  26. package/dist/formatters/chunker.js.map +1 -0
  27. package/dist/formatters/embedBuilder.d.ts +28 -0
  28. package/dist/formatters/embedBuilder.js +32 -0
  29. package/dist/formatters/embedBuilder.js.map +1 -0
  30. package/dist/formatters/toolFormatter.d.ts +4 -0
  31. package/dist/formatters/toolFormatter.js +90 -0
  32. package/dist/formatters/toolFormatter.js.map +1 -0
  33. package/dist/guild.d.ts +22 -0
  34. package/dist/guild.js +41 -0
  35. package/dist/guild.js.map +1 -0
  36. package/dist/interactions/directoryBrowser.d.ts +61 -0
  37. package/dist/interactions/directoryBrowser.js +611 -0
  38. package/dist/interactions/directoryBrowser.js.map +1 -0
  39. package/dist/interactions/index.d.ts +5 -0
  40. package/dist/interactions/index.js +92 -0
  41. package/dist/interactions/index.js.map +1 -0
  42. package/dist/interactions/permissionHandler.d.ts +11 -0
  43. package/dist/interactions/permissionHandler.js +107 -0
  44. package/dist/interactions/permissionHandler.js.map +1 -0
  45. package/dist/interactions/sessionControls.d.ts +9 -0
  46. package/dist/interactions/sessionControls.js +95 -0
  47. package/dist/interactions/sessionControls.js.map +1 -0
  48. package/dist/sessions/eventHandler.d.ts +3 -0
  49. package/dist/sessions/eventHandler.js +209 -0
  50. package/dist/sessions/eventHandler.js.map +1 -0
  51. package/dist/sessions/sessionManager.d.ts +29 -0
  52. package/dist/sessions/sessionManager.js +203 -0
  53. package/dist/sessions/sessionManager.js.map +1 -0
  54. package/dist/sessions/sessionStore.d.ts +4 -0
  55. package/dist/sessions/sessionStore.js +29 -0
  56. package/dist/sessions/sessionStore.js.map +1 -0
  57. package/dist/sessions/streamHandler.d.ts +18 -0
  58. package/dist/sessions/streamHandler.js +119 -0
  59. package/dist/sessions/streamHandler.js.map +1 -0
  60. package/dist/sessions/toolProgress.d.ts +14 -0
  61. package/dist/sessions/toolProgress.js +65 -0
  62. package/dist/sessions/toolProgress.js.map +1 -0
  63. package/dist/sessions/usageTracker.d.ts +12 -0
  64. package/dist/sessions/usageTracker.js +222 -0
  65. package/dist/sessions/usageTracker.js.map +1 -0
  66. package/dist/setup.d.ts +1 -0
  67. package/dist/setup.js +101 -0
  68. package/dist/setup.js.map +1 -0
  69. package/dist/utils/filesystem.d.ts +11 -0
  70. package/dist/utils/filesystem.js +26 -0
  71. package/dist/utils/filesystem.js.map +1 -0
  72. package/dist/utils/logger.d.ts +1 -0
  73. package/dist/utils/logger.js +3 -0
  74. package/dist/utils/logger.js.map +1 -0
  75. package/dist/utils/plugins.d.ts +6 -0
  76. package/dist/utils/plugins.js +66 -0
  77. package/dist/utils/plugins.js.map +1 -0
  78. package/package.json +45 -0
@@ -0,0 +1,222 @@
1
+ import { EmbedBuilder } from 'discord.js';
2
+ import { COLORS } from '../formatters/embedBuilder.js';
3
+ import { loadGuildConfig } from '../guild.js';
4
+ import { sessionManager } from './sessionManager.js';
5
+ const rateLimitState = { lastUpdated: 0 };
6
+ const usageAccum = {
7
+ currentSessionId: '',
8
+ sessionCostUsd: 0,
9
+ sessionInputTokens: 0,
10
+ sessionOutputTokens: 0,
11
+ totalCostUsd: 0,
12
+ totalInputTokens: 0,
13
+ totalOutputTokens: 0,
14
+ modelUsage: {},
15
+ };
16
+ let debounceTimer = null;
17
+ let trackerClient = null;
18
+ // ---------------------------------------------------------------------------
19
+ // Helpers
20
+ // ---------------------------------------------------------------------------
21
+ function progressBar(utilization, length = 20) {
22
+ const clamped = Math.max(0, Math.min(1, utilization));
23
+ const filled = Math.round(clamped * length);
24
+ return '\u2588'.repeat(filled) + '\u2591'.repeat(length - filled);
25
+ }
26
+ function statusEmoji(status) {
27
+ switch (status) {
28
+ case 'allowed': return '\u2705';
29
+ case 'allowed_warning': return '\u26a0\ufe0f';
30
+ case 'rejected': return '\u274c';
31
+ default: return '\u2753';
32
+ }
33
+ }
34
+ function statusColor(status) {
35
+ switch (status) {
36
+ case 'allowed': return COLORS.IDLE;
37
+ case 'allowed_warning': return COLORS.STREAMING;
38
+ case 'rejected': return COLORS.STOPPED;
39
+ default: return COLORS.ARCHIVED;
40
+ }
41
+ }
42
+ function formatTokens(n) {
43
+ if (n >= 1_000_000)
44
+ return `${(n / 1_000_000).toFixed(1)}M`;
45
+ if (n >= 1_000)
46
+ return `${(n / 1_000).toFixed(1)}K`;
47
+ return String(n);
48
+ }
49
+ function formatCost(usd) {
50
+ if (usd < 0.01)
51
+ return `$${usd.toFixed(4)}`;
52
+ return `$${usd.toFixed(2)}`;
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Embed builder
56
+ // ---------------------------------------------------------------------------
57
+ function formatRateLimit(label, info) {
58
+ const parts = [];
59
+ if (info.utilization != null) {
60
+ const pct = Math.round(info.utilization * 100);
61
+ parts.push(`${progressBar(info.utilization)} ${pct}%`);
62
+ }
63
+ parts.push(`${statusEmoji(info.status)} ${info.status}`);
64
+ if (info.resetsAt) {
65
+ parts.push(`Resets <t:${info.resetsAt}:R>`);
66
+ }
67
+ return parts.join('\n');
68
+ }
69
+ export function buildUsageEmbed(state) {
70
+ const s = state ?? rateLimitState;
71
+ const u = usageAccum;
72
+ const overall = s.fiveHour ?? s.sevenDay ?? s.sevenDayOpus ?? s.sevenDaySonnet;
73
+ const color = statusColor(overall?.status);
74
+ const embed = new EmbedBuilder()
75
+ .setTitle('\ud83d\udcca Claude Usage')
76
+ .setColor(color);
77
+ // --- Current Session ---
78
+ const sessionLines = [];
79
+ if (u.sessionCostUsd > 0 || u.sessionInputTokens > 0) {
80
+ sessionLines.push(`Cost: **${formatCost(u.sessionCostUsd)}**`);
81
+ sessionLines.push(`Tokens: ${formatTokens(u.sessionInputTokens)} in / ${formatTokens(u.sessionOutputTokens)} out`);
82
+ }
83
+ else {
84
+ sessionLines.push('No activity yet');
85
+ }
86
+ embed.addFields({ name: '\ud83d\udcac Current Session', value: sessionLines.join('\n') });
87
+ // --- Total (all sessions since bot start) ---
88
+ if (u.totalCostUsd > 0) {
89
+ const totalLines = [];
90
+ totalLines.push(`Cost: **${formatCost(u.totalCostUsd)}**`);
91
+ totalLines.push(`Tokens: ${formatTokens(u.totalInputTokens)} in / ${formatTokens(u.totalOutputTokens)} out`);
92
+ // Per-model breakdown
93
+ const models = Object.entries(u.modelUsage);
94
+ if (models.length > 0) {
95
+ for (const [model, mu] of models) {
96
+ const shortName = model.replace('claude-', '').replace(/-\d+$/, '');
97
+ totalLines.push(`\u2022 ${shortName}: ${formatCost(mu.costUSD)} (${formatTokens(mu.inputTokens + mu.outputTokens)} tokens)`);
98
+ }
99
+ }
100
+ embed.addFields({ name: '\ud83d\udcc8 All Sessions (since bot start)', value: totalLines.join('\n') });
101
+ }
102
+ // --- Rate Limits ---
103
+ if (s.fiveHour) {
104
+ embed.addFields({ name: '\u23f0 5-Hour Limit', value: formatRateLimit('5-Hour', s.fiveHour), inline: true });
105
+ }
106
+ if (s.sevenDay) {
107
+ embed.addFields({ name: '\ud83d\udcc5 Weekly Limit', value: formatRateLimit('Weekly', s.sevenDay), inline: true });
108
+ }
109
+ if (s.sevenDayOpus) {
110
+ embed.addFields({ name: '\ud83d\udcc5 Weekly (Opus)', value: formatRateLimit('Weekly Opus', s.sevenDayOpus), inline: true });
111
+ }
112
+ if (s.sevenDaySonnet) {
113
+ embed.addFields({ name: '\ud83d\udcc5 Weekly (Sonnet)', value: formatRateLimit('Weekly Sonnet', s.sevenDaySonnet), inline: true });
114
+ }
115
+ if (!s.fiveHour && !s.sevenDay && !s.sevenDayOpus && !s.sevenDaySonnet) {
116
+ embed.addFields({ name: 'Rate Limits', value: 'Waiting for data... Start a session to see limits.' });
117
+ }
118
+ // --- Last Updated ---
119
+ if (s.lastUpdated > 0) {
120
+ embed.setFooter({ text: `Last updated` });
121
+ embed.setTimestamp(s.lastUpdated);
122
+ }
123
+ return embed;
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Update logic
127
+ // ---------------------------------------------------------------------------
128
+ async function updateUsageEmbed(guildId) {
129
+ if (!trackerClient)
130
+ return;
131
+ const config = loadGuildConfig(guildId);
132
+ if (!config?.usageChannelId || !config?.usageMessageId)
133
+ return;
134
+ const channel = trackerClient.channels.cache.get(config.usageChannelId);
135
+ if (!channel?.isTextBased())
136
+ return;
137
+ try {
138
+ const textChannel = channel;
139
+ const msg = await textChannel.messages.fetch(config.usageMessageId).catch(() => null);
140
+ if (msg) {
141
+ await msg.edit({ embeds: [buildUsageEmbed()] });
142
+ }
143
+ }
144
+ catch (err) {
145
+ console.error('[usage] Failed to update usage embed:', err);
146
+ }
147
+ }
148
+ function scheduleUpdate(guildId) {
149
+ if (debounceTimer)
150
+ return;
151
+ debounceTimer = setTimeout(() => {
152
+ debounceTimer = null;
153
+ void updateUsageEmbed(guildId);
154
+ }, 5000);
155
+ }
156
+ // ---------------------------------------------------------------------------
157
+ // Event handlers
158
+ // ---------------------------------------------------------------------------
159
+ let trackerRegistered = false;
160
+ export function setupUsageTracker(client) {
161
+ if (trackerRegistered)
162
+ return;
163
+ trackerRegistered = true;
164
+ trackerClient = client;
165
+ // Rate limit events
166
+ sessionManager.on('rate_limit', (guildId, info) => {
167
+ rateLimitState.lastUpdated = Date.now();
168
+ switch (info.rateLimitType) {
169
+ case 'five_hour':
170
+ rateLimitState.fiveHour = info;
171
+ break;
172
+ case 'seven_day_opus':
173
+ rateLimitState.sevenDayOpus = info;
174
+ break;
175
+ case 'seven_day_sonnet':
176
+ rateLimitState.sevenDaySonnet = info;
177
+ break;
178
+ case 'seven_day':
179
+ rateLimitState.sevenDay = info;
180
+ break;
181
+ default:
182
+ rateLimitState.fiveHour = info;
183
+ break;
184
+ }
185
+ scheduleUpdate(guildId);
186
+ });
187
+ // Result events -- accumulate cost and token usage
188
+ sessionManager.on('result', (channelId, msg) => {
189
+ const session = sessionManager.getSession(channelId);
190
+ if (!session)
191
+ return;
192
+ // Track current session
193
+ if (usageAccum.currentSessionId !== session.sessionId) {
194
+ // New session -- reset session counters
195
+ usageAccum.currentSessionId = session.sessionId;
196
+ usageAccum.sessionCostUsd = 0;
197
+ usageAccum.sessionInputTokens = 0;
198
+ usageAccum.sessionOutputTokens = 0;
199
+ }
200
+ usageAccum.sessionCostUsd = msg.total_cost_usd ?? usageAccum.sessionCostUsd;
201
+ if (msg.usage) {
202
+ usageAccum.sessionInputTokens += msg.usage.input_tokens ?? 0;
203
+ usageAccum.sessionOutputTokens += msg.usage.output_tokens ?? 0;
204
+ usageAccum.totalInputTokens += msg.usage.input_tokens ?? 0;
205
+ usageAccum.totalOutputTokens += msg.usage.output_tokens ?? 0;
206
+ }
207
+ usageAccum.totalCostUsd += msg.total_cost_usd ?? 0;
208
+ // Per-model breakdown from modelUsage
209
+ if (msg.modelUsage) {
210
+ for (const [model, mu] of Object.entries(msg.modelUsage)) {
211
+ const existing = usageAccum.modelUsage[model] ?? { costUSD: 0, inputTokens: 0, outputTokens: 0 };
212
+ existing.costUSD += mu.costUSD ?? 0;
213
+ existing.inputTokens += mu.inputTokens ?? 0;
214
+ existing.outputTokens += mu.outputTokens ?? 0;
215
+ usageAccum.modelUsage[model] = existing;
216
+ }
217
+ }
218
+ rateLimitState.lastUpdated = Date.now();
219
+ scheduleUpdate(session.guildId);
220
+ });
221
+ }
222
+ //# sourceMappingURL=usageTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usageTracker.js","sourceRoot":"","sources":["../../src/sessions/usageTracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runSetup(): Promise<void>;
package/dist/setup.js ADDED
@@ -0,0 +1,101 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ import { input, confirm } from '@inquirer/prompts';
5
+ import open from 'open';
6
+ import { configExists, loadConfig, saveConfig, } from './config.js';
7
+ /** Permission bits required by the bot. */
8
+ const PERMISSION_BITS = BigInt(0x10) | // Manage Channels
9
+ BigInt(0x800) | // Send Messages
10
+ BigInt(0x4000) | // Embed Links
11
+ BigInt(0x8000) | // Attach Files
12
+ BigInt(0x10000) | // Read Message History
13
+ BigInt(0x40000) | // Use External Emojis
14
+ BigInt(0x40) | // Add Reactions
15
+ BigInt(0x400000000) | // Manage Threads
16
+ BigInt(0x800000000) | // Create Public Threads
17
+ BigInt(0x2000); // Manage Messages
18
+ function maskToken(token) {
19
+ if (token.length <= 8)
20
+ return '****';
21
+ return token.slice(0, 4) + '****' + token.slice(-4);
22
+ }
23
+ export async function runSetup() {
24
+ console.log('\n=== Agent4Discord Setup ===\n');
25
+ // Check for existing config
26
+ if (configExists()) {
27
+ let existing;
28
+ try {
29
+ existing = loadConfig();
30
+ }
31
+ catch {
32
+ console.log('Existing config is invalid. Starting fresh.\n');
33
+ existing = undefined;
34
+ }
35
+ if (existing) {
36
+ console.log(`Existing config found. Token: ${maskToken(existing.discordToken)}`);
37
+ const reconfigure = await confirm({
38
+ message: 'Do you want to reconfigure?',
39
+ default: false,
40
+ });
41
+ if (!reconfigure) {
42
+ console.log('Setup cancelled.');
43
+ return;
44
+ }
45
+ console.log('');
46
+ }
47
+ }
48
+ // Step 1: Bot token
49
+ console.log('Step 1: Discord Bot Token');
50
+ console.log(' Create a bot at https://discord.com/developers/applications');
51
+ console.log(' Go to Bot tab -> Copy the token\n');
52
+ const discordToken = await input({
53
+ message: 'Enter your bot token:',
54
+ validate: (val) => (val.trim().length > 0 ? true : 'Token is required'),
55
+ });
56
+ // Step 2: Client ID
57
+ console.log('\nStep 2: Application Client ID');
58
+ console.log(' Found on the General Information tab of your application\n');
59
+ const discordClientId = await input({
60
+ message: 'Enter your Client ID:',
61
+ validate: (val) => (val.trim().length > 0 ? true : 'Client ID is required'),
62
+ });
63
+ // Step 3: Message Content Intent
64
+ console.log('\nStep 3: Message Content Intent');
65
+ console.log(' In the Bot tab, enable "Message Content Intent" under Privileged Gateway Intents\n');
66
+ await confirm({
67
+ message: 'Have you enabled Message Content Intent?',
68
+ default: true,
69
+ });
70
+ // Check Claude Code auth
71
+ const claudeDir = path.join(os.homedir(), '.claude');
72
+ if (fs.existsSync(claudeDir)) {
73
+ console.log('\n[OK] Claude Code directory found (~/.claude/)');
74
+ }
75
+ else {
76
+ console.log('\n[INFO] Claude Code directory not found (~/.claude/).');
77
+ console.log(' Make sure Claude Code is installed and authenticated (run: claude login)');
78
+ }
79
+ // Generate invite URL and open
80
+ const permissions = PERMISSION_BITS.toString();
81
+ const inviteUrl = `https://discord.com/api/oauth2/authorize?client_id=${encodeURIComponent(discordClientId.trim())}` +
82
+ `&permissions=${permissions}&scope=bot%20applications.commands`;
83
+ console.log(`\nOpening invite URL in your browser...\n ${inviteUrl}\n`);
84
+ try {
85
+ await open(inviteUrl);
86
+ }
87
+ catch {
88
+ console.log(' Could not open browser. Please visit the URL above manually.');
89
+ }
90
+ // Save config
91
+ const config = {
92
+ discordToken: discordToken.trim(),
93
+ discordClientId: discordClientId.trim(),
94
+ claudeModel: 'opus',
95
+ permissionMode: 'default',
96
+ logLevel: 'info',
97
+ };
98
+ saveConfig(config);
99
+ console.log('\nConfig saved. Run "agent4discord" to start the bot.');
100
+ }
101
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * List subdirectories of the given path.
3
+ * Excludes hidden directories (starting with '.') and 'node_modules'.
4
+ * Returns sorted array of directory names (not full paths).
5
+ */
6
+ export declare function listDirectories(dirPath: string): Promise<string[]>;
7
+ /**
8
+ * Validate that the target path is a real absolute path (no traversal tricks).
9
+ * Self-hosted bot -- no homedir restriction.
10
+ */
11
+ export declare function isPathSafe(targetPath: string): boolean;
@@ -0,0 +1,26 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ /**
4
+ * List subdirectories of the given path.
5
+ * Excludes hidden directories (starting with '.') and 'node_modules'.
6
+ * Returns sorted array of directory names (not full paths).
7
+ */
8
+ export async function listDirectories(dirPath) {
9
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
10
+ const dirs = entries
11
+ .filter((entry) => entry.isDirectory() &&
12
+ !entry.name.startsWith('.') &&
13
+ entry.name !== 'node_modules')
14
+ .map((entry) => entry.name)
15
+ .sort((a, b) => a.localeCompare(b));
16
+ return dirs;
17
+ }
18
+ /**
19
+ * Validate that the target path is a real absolute path (no traversal tricks).
20
+ * Self-hosted bot -- no homedir restriction.
21
+ */
22
+ export function isPathSafe(targetPath) {
23
+ const resolved = path.resolve(targetPath);
24
+ return resolved === targetPath || path.isAbsolute(resolved);
25
+ }
26
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../src/utils/filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAe;IACnD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnE,MAAM,IAAI,GAAG,OAAO;SACjB,MAAM,CACL,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,WAAW,EAAE;QACnB,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAC3B,KAAK,CAAC,IAAI,KAAK,cAAc,CAChC;SACA,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,OAAO,QAAQ,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export {};
2
+ // Structured logging
3
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";AAAA,qBAAqB"}
@@ -0,0 +1,6 @@
1
+ import type { SdkPluginConfig } from '@anthropic-ai/claude-agent-sdk';
2
+ /**
3
+ * Resolve enabled plugins from ~/.claude/ config files.
4
+ * Returns an array of SdkPluginConfig for passing to query() options.
5
+ */
6
+ export declare function resolvePlugins(): SdkPluginConfig[];
@@ -0,0 +1,66 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ const CLAUDE_DIR = path.join(os.homedir(), '.claude');
5
+ const SETTINGS_PATH = path.join(CLAUDE_DIR, 'settings.json');
6
+ const INSTALLED_PLUGINS_PATH = path.join(CLAUDE_DIR, 'plugins', 'installed_plugins.json');
7
+ /**
8
+ * Resolve enabled plugins from ~/.claude/ config files.
9
+ * Returns an array of SdkPluginConfig for passing to query() options.
10
+ */
11
+ export function resolvePlugins() {
12
+ // Read settings.json for enabled plugins
13
+ let settings;
14
+ try {
15
+ const raw = fs.readFileSync(SETTINGS_PATH, 'utf-8');
16
+ settings = JSON.parse(raw);
17
+ }
18
+ catch {
19
+ return [];
20
+ }
21
+ const enabledPlugins = settings.enabledPlugins;
22
+ if (!enabledPlugins || typeof enabledPlugins !== 'object') {
23
+ return [];
24
+ }
25
+ const enabledNames = Object.entries(enabledPlugins)
26
+ .filter(([, enabled]) => enabled === true)
27
+ .map(([name]) => name);
28
+ if (enabledNames.length === 0)
29
+ return [];
30
+ // Read installed_plugins.json for install paths
31
+ let installed;
32
+ try {
33
+ const raw = fs.readFileSync(INSTALLED_PLUGINS_PATH, 'utf-8');
34
+ installed = JSON.parse(raw);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ if (!installed.plugins || typeof installed.plugins !== 'object') {
40
+ return [];
41
+ }
42
+ // Cross-reference: enabled + installed + directory exists
43
+ const result = [];
44
+ for (const name of enabledNames) {
45
+ const entries = installed.plugins[name];
46
+ if (!entries || entries.length === 0) {
47
+ console.warn(`[plugins] Enabled plugin "${name}" not found in installed_plugins.json, skipping`);
48
+ continue;
49
+ }
50
+ const installPath = entries[0].installPath;
51
+ if (!installPath) {
52
+ console.warn(`[plugins] Enabled plugin "${name}" has no installPath, skipping`);
53
+ continue;
54
+ }
55
+ if (!fs.existsSync(installPath)) {
56
+ console.warn(`[plugins] Plugin "${name}" install path does not exist: ${installPath}, skipping`);
57
+ continue;
58
+ }
59
+ result.push({ type: 'local', path: installPath });
60
+ }
61
+ if (result.length > 0) {
62
+ console.log(`[plugins] Loaded ${result.length} plugin(s): ${enabledNames.filter((n) => result.some((r) => installed.plugins[n]?.[0]?.installPath === r.path)).join(', ')}`);
63
+ }
64
+ return result;
65
+ }
66
+ //# sourceMappingURL=plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../src/utils/plugins.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "agent4discord",
3
+ "version": "0.1.0",
4
+ "description": "Remote Claude Code sessions through Discord",
5
+ "type": "module",
6
+ "bin": {
7
+ "agent4discord": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsx watch src/cli.ts",
15
+ "start": "node dist/cli.js",
16
+ "typecheck": "tsc --noEmit",
17
+ "test": "vitest run",
18
+ "lint": "eslint src/"
19
+ },
20
+ "keywords": [
21
+ "discord",
22
+ "claude",
23
+ "claude-code",
24
+ "agent",
25
+ "bot"
26
+ ],
27
+ "license": "MIT",
28
+ "engines": {
29
+ "node": ">=20.0.0"
30
+ },
31
+ "dependencies": {
32
+ "discord.js": "^14.18.0",
33
+ "@anthropic-ai/claude-agent-sdk": "^0.2.0",
34
+ "@discordjs/rest": "^2.4.0",
35
+ "@inquirer/prompts": "^8.0.0",
36
+ "open": "^11.0.0"
37
+ },
38
+ "devDependencies": {
39
+ "typescript": "~5.7.0",
40
+ "tsx": "^4.0.0",
41
+ "vitest": "^3.0.0",
42
+ "eslint": "^9.0.0",
43
+ "@types/node": "^20.0.0"
44
+ }
45
+ }