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.
- package/README.ko.md +134 -0
- package/README.md +170 -0
- package/dist/bot.d.ts +1 -0
- package/dist/bot.js +114 -0
- package/dist/bot.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.js +44 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.js +152 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/model.d.ts +5 -0
- package/dist/commands/model.js +65 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/resume.d.ts +6 -0
- package/dist/commands/resume.js +113 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.js +49 -0
- package/dist/config.js.map +1 -0
- package/dist/formatters/chunker.d.ts +5 -0
- package/dist/formatters/chunker.js +46 -0
- package/dist/formatters/chunker.js.map +1 -0
- package/dist/formatters/embedBuilder.d.ts +28 -0
- package/dist/formatters/embedBuilder.js +32 -0
- package/dist/formatters/embedBuilder.js.map +1 -0
- package/dist/formatters/toolFormatter.d.ts +4 -0
- package/dist/formatters/toolFormatter.js +90 -0
- package/dist/formatters/toolFormatter.js.map +1 -0
- package/dist/guild.d.ts +22 -0
- package/dist/guild.js +41 -0
- package/dist/guild.js.map +1 -0
- package/dist/interactions/directoryBrowser.d.ts +61 -0
- package/dist/interactions/directoryBrowser.js +611 -0
- package/dist/interactions/directoryBrowser.js.map +1 -0
- package/dist/interactions/index.d.ts +5 -0
- package/dist/interactions/index.js +92 -0
- package/dist/interactions/index.js.map +1 -0
- package/dist/interactions/permissionHandler.d.ts +11 -0
- package/dist/interactions/permissionHandler.js +107 -0
- package/dist/interactions/permissionHandler.js.map +1 -0
- package/dist/interactions/sessionControls.d.ts +9 -0
- package/dist/interactions/sessionControls.js +95 -0
- package/dist/interactions/sessionControls.js.map +1 -0
- package/dist/sessions/eventHandler.d.ts +3 -0
- package/dist/sessions/eventHandler.js +209 -0
- package/dist/sessions/eventHandler.js.map +1 -0
- package/dist/sessions/sessionManager.d.ts +29 -0
- package/dist/sessions/sessionManager.js +203 -0
- package/dist/sessions/sessionManager.js.map +1 -0
- package/dist/sessions/sessionStore.d.ts +4 -0
- package/dist/sessions/sessionStore.js +29 -0
- package/dist/sessions/sessionStore.js.map +1 -0
- package/dist/sessions/streamHandler.d.ts +18 -0
- package/dist/sessions/streamHandler.js +119 -0
- package/dist/sessions/streamHandler.js.map +1 -0
- package/dist/sessions/toolProgress.d.ts +14 -0
- package/dist/sessions/toolProgress.js +65 -0
- package/dist/sessions/toolProgress.js.map +1 -0
- package/dist/sessions/usageTracker.d.ts +12 -0
- package/dist/sessions/usageTracker.js +222 -0
- package/dist/sessions/usageTracker.js.map +1 -0
- package/dist/setup.d.ts +1 -0
- package/dist/setup.js +101 -0
- package/dist/setup.js.map +1 -0
- package/dist/utils/filesystem.d.ts +11 -0
- package/dist/utils/filesystem.js +26 -0
- package/dist/utils/filesystem.js.map +1 -0
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.js +3 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/plugins.d.ts +6 -0
- package/dist/utils/plugins.js +66 -0
- package/dist/utils/plugins.js.map +1 -0
- 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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"}
|
package/dist/setup.d.ts
ADDED
|
@@ -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 @@
|
|
|
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
|
+
}
|