agentcord 0.1.6 → 0.1.7
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/dist/{bot-RT4CJNKG.js → bot-G6464LRS.js} +104 -13
- package/dist/cli.js +1 -1
- package/package.json +1 -1
|
@@ -53,7 +53,11 @@ import {
|
|
|
53
53
|
Routes
|
|
54
54
|
} from "discord.js";
|
|
55
55
|
function getCommandDefinitions() {
|
|
56
|
-
const claude = new SlashCommandBuilder().setName("claude").setDescription("Manage Claude Code sessions").addSubcommand((sub) => sub.setName("new").setDescription("Create a new Claude Code session").addStringOption((opt) => opt.setName("name").setDescription("Session name").setRequired(true)).addStringOption((opt) => opt.setName("directory").setDescription("Working directory (default: configured default)"))).addSubcommand((sub) => sub.setName("resume").setDescription("Resume an existing Claude Code session from terminal").addStringOption((opt) => opt.setName("session-id").setDescription("Claude Code session UUID").setRequired(true).setAutocomplete(true)).addStringOption((opt) => opt.setName("name").setDescription("Name for the Discord channel").setRequired(true)).addStringOption((opt) => opt.setName("directory").setDescription("Working directory (default: configured default)"))).addSubcommand((sub) => sub.setName("list").setDescription("List active sessions")).addSubcommand((sub) => sub.setName("end").setDescription("End the session in this channel")).addSubcommand((sub) => sub.setName("continue").setDescription("Continue the last conversation")).addSubcommand((sub) => sub.setName("stop").setDescription("Stop current generation")).addSubcommand((sub) => sub.setName("output").setDescription("Show recent conversation output").addIntegerOption((opt) => opt.setName("lines").setDescription("Number of lines (default 50)").setMinValue(1).setMaxValue(500))).addSubcommand((sub) => sub.setName("attach").setDescription("Show tmux attach command for terminal access")).addSubcommand((sub) => sub.setName("sync").setDescription("Reconnect orphaned tmux sessions")).addSubcommand((sub) => sub.setName("model").setDescription("Change the model for this session").addStringOption((opt) => opt.setName("model").setDescription("Model name (e.g. claude-sonnet-4-5-20250929)").setRequired(true))).addSubcommand((sub) => sub.setName("verbose").setDescription("Toggle showing tool calls and results in this session"))
|
|
56
|
+
const claude = new SlashCommandBuilder().setName("claude").setDescription("Manage Claude Code sessions").addSubcommand((sub) => sub.setName("new").setDescription("Create a new Claude Code session").addStringOption((opt) => opt.setName("name").setDescription("Session name").setRequired(true)).addStringOption((opt) => opt.setName("directory").setDescription("Working directory (default: configured default)"))).addSubcommand((sub) => sub.setName("resume").setDescription("Resume an existing Claude Code session from terminal").addStringOption((opt) => opt.setName("session-id").setDescription("Claude Code session UUID").setRequired(true).setAutocomplete(true)).addStringOption((opt) => opt.setName("name").setDescription("Name for the Discord channel").setRequired(true)).addStringOption((opt) => opt.setName("directory").setDescription("Working directory (default: configured default)"))).addSubcommand((sub) => sub.setName("list").setDescription("List active sessions")).addSubcommand((sub) => sub.setName("end").setDescription("End the session in this channel")).addSubcommand((sub) => sub.setName("continue").setDescription("Continue the last conversation")).addSubcommand((sub) => sub.setName("stop").setDescription("Stop current generation")).addSubcommand((sub) => sub.setName("output").setDescription("Show recent conversation output").addIntegerOption((opt) => opt.setName("lines").setDescription("Number of lines (default 50)").setMinValue(1).setMaxValue(500))).addSubcommand((sub) => sub.setName("attach").setDescription("Show tmux attach command for terminal access")).addSubcommand((sub) => sub.setName("sync").setDescription("Reconnect orphaned tmux sessions")).addSubcommand((sub) => sub.setName("model").setDescription("Change the model for this session").addStringOption((opt) => opt.setName("model").setDescription("Model name (e.g. claude-sonnet-4-5-20250929)").setRequired(true))).addSubcommand((sub) => sub.setName("verbose").setDescription("Toggle showing tool calls and results in this session")).addSubcommand((sub) => sub.setName("mode").setDescription("Set session mode (auto/plan/normal)").addStringOption((opt) => opt.setName("mode").setDescription("Session mode").setRequired(true).addChoices(
|
|
57
|
+
{ name: "Auto \u2014 full autonomy", value: "auto" },
|
|
58
|
+
{ name: "Plan \u2014 plan before executing", value: "plan" },
|
|
59
|
+
{ name: "Normal \u2014 ask before destructive ops", value: "normal" }
|
|
60
|
+
)));
|
|
57
61
|
const shell = new SlashCommandBuilder().setName("shell").setDescription("Run shell commands in the session directory").addSubcommand((sub) => sub.setName("run").setDescription("Execute a shell command").addStringOption((opt) => opt.setName("command").setDescription("Command to run").setRequired(true))).addSubcommand((sub) => sub.setName("processes").setDescription("List running processes")).addSubcommand((sub) => sub.setName("kill").setDescription("Kill a running process").addIntegerOption((opt) => opt.setName("pid").setDescription("Process ID to kill").setRequired(true)));
|
|
58
62
|
const agent = new SlashCommandBuilder().setName("agent").setDescription("Manage agent personas").addSubcommand((sub) => sub.setName("use").setDescription("Switch to an agent persona").addStringOption((opt) => opt.setName("persona").setDescription("Agent persona name").setRequired(true).addChoices(
|
|
59
63
|
{ name: "Code Reviewer", value: "code-reviewer" },
|
|
@@ -446,6 +450,11 @@ function detectYesNoPrompt(text) {
|
|
|
446
450
|
|
|
447
451
|
// src/session-manager.ts
|
|
448
452
|
var SESSION_PREFIX = "claude-";
|
|
453
|
+
var MODE_PROMPTS = {
|
|
454
|
+
auto: "",
|
|
455
|
+
plan: "You MUST use EnterPlanMode at the start of every task. Present your plan for user approval before making any code changes. Do not write or edit files until the user approves the plan.",
|
|
456
|
+
normal: "Before performing destructive or significant operations (deleting files, running dangerous commands, making large refactors, writing to many files), use AskUserQuestion to confirm with the user first. Ask for explicit approval before proceeding with changes."
|
|
457
|
+
};
|
|
449
458
|
var sessionStore = new Store("sessions.json");
|
|
450
459
|
var sessions = /* @__PURE__ */ new Map();
|
|
451
460
|
var channelToSession = /* @__PURE__ */ new Map();
|
|
@@ -473,6 +482,7 @@ async function loadSessions() {
|
|
|
473
482
|
sessions.set(s.id, {
|
|
474
483
|
...s,
|
|
475
484
|
verbose: s.verbose ?? false,
|
|
485
|
+
mode: s.mode ?? "auto",
|
|
476
486
|
isGenerating: false
|
|
477
487
|
});
|
|
478
488
|
channelToSession.set(s.channelId, s.id);
|
|
@@ -499,6 +509,7 @@ async function saveSessions() {
|
|
|
499
509
|
model: s.model,
|
|
500
510
|
agentPersona: s.agentPersona,
|
|
501
511
|
verbose: s.verbose || void 0,
|
|
512
|
+
mode: s.mode !== "auto" ? s.mode : void 0,
|
|
502
513
|
createdAt: s.createdAt,
|
|
503
514
|
lastActivity: s.lastActivity,
|
|
504
515
|
messageCount: s.messageCount,
|
|
@@ -532,6 +543,7 @@ async function createSession(name, directory, channelId, projectName, claudeSess
|
|
|
532
543
|
tmuxName,
|
|
533
544
|
claudeSessionId,
|
|
534
545
|
verbose: false,
|
|
546
|
+
mode: "auto",
|
|
535
547
|
isGenerating: false,
|
|
536
548
|
createdAt: Date.now(),
|
|
537
549
|
lastActivity: Date.now(),
|
|
@@ -601,6 +613,13 @@ function setVerbose(sessionId, verbose) {
|
|
|
601
613
|
saveSessions();
|
|
602
614
|
}
|
|
603
615
|
}
|
|
616
|
+
function setMode(sessionId, mode) {
|
|
617
|
+
const session = sessions.get(sessionId);
|
|
618
|
+
if (session) {
|
|
619
|
+
session.mode = mode;
|
|
620
|
+
saveSessions();
|
|
621
|
+
}
|
|
622
|
+
}
|
|
604
623
|
function setAgentPersona(sessionId, persona) {
|
|
605
624
|
const session = sessions.get(sessionId);
|
|
606
625
|
if (session) {
|
|
@@ -616,6 +635,8 @@ function buildSystemPrompt(session) {
|
|
|
616
635
|
const agent = getAgent(session.agentPersona);
|
|
617
636
|
if (agent?.systemPrompt) parts.push(agent.systemPrompt);
|
|
618
637
|
}
|
|
638
|
+
const modePrompt = MODE_PROMPTS[session.mode];
|
|
639
|
+
if (modePrompt) parts.push(modePrompt);
|
|
619
640
|
if (parts.length > 0) {
|
|
620
641
|
return { type: "preset", preset: "claude_code", append: parts.join("\n\n") };
|
|
621
642
|
}
|
|
@@ -806,6 +827,20 @@ function makeOptionButtons(sessionId, options) {
|
|
|
806
827
|
}
|
|
807
828
|
return rows;
|
|
808
829
|
}
|
|
830
|
+
function makeModeButtons(sessionId, currentMode) {
|
|
831
|
+
const modes = [
|
|
832
|
+
{ id: "auto", label: "\u26A1 Auto" },
|
|
833
|
+
{ id: "plan", label: "\u{1F4CB} Plan" },
|
|
834
|
+
{ id: "normal", label: "\u{1F6E1}\uFE0F Normal" }
|
|
835
|
+
];
|
|
836
|
+
const row = new ActionRowBuilder();
|
|
837
|
+
for (const m of modes) {
|
|
838
|
+
row.addComponents(
|
|
839
|
+
new ButtonBuilder().setCustomId(`mode:${sessionId}:${m.id}`).setLabel(m.label).setStyle(m.id === currentMode ? ButtonStyle.Primary : ButtonStyle.Secondary).setDisabled(m.id === currentMode)
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
return row;
|
|
843
|
+
}
|
|
809
844
|
function makeYesNoButtons(sessionId) {
|
|
810
845
|
return new ActionRowBuilder().addComponents(
|
|
811
846
|
new ButtonBuilder().setCustomId(`confirm:${sessionId}:yes`).setLabel("Yes").setStyle(ButtonStyle.Success),
|
|
@@ -1021,7 +1056,7 @@ function renderTaskListEmbed(resultText) {
|
|
|
1021
1056
|
}
|
|
1022
1057
|
return new EmbedBuilder().setColor(10181046).setTitle("\u{1F4CB} Task Board").setDescription(truncate(formatted, 4e3));
|
|
1023
1058
|
}
|
|
1024
|
-
async function handleOutputStream(stream, channel, sessionId, verbose = false) {
|
|
1059
|
+
async function handleOutputStream(stream, channel, sessionId, verbose = false, mode = "auto") {
|
|
1025
1060
|
const streamer = new MessageStreamer(channel, sessionId);
|
|
1026
1061
|
let currentToolName = null;
|
|
1027
1062
|
let currentToolInput = "";
|
|
@@ -1151,7 +1186,8 @@ ${displayResult}
|
|
|
1151
1186
|
const embed = new EmbedBuilder().setColor(isSuccess ? 3066993 : 15158332).setTitle(isSuccess ? "Completed" : "Error").addFields(
|
|
1152
1187
|
{ name: "Cost", value: `$${cost}`, inline: true },
|
|
1153
1188
|
{ name: "Duration", value: duration, inline: true },
|
|
1154
|
-
{ name: "Turns", value: `${turns}`, inline: true }
|
|
1189
|
+
{ name: "Turns", value: `${turns}`, inline: true },
|
|
1190
|
+
{ name: "Mode", value: { auto: "\u26A1 Auto", plan: "\u{1F4CB} Plan", normal: "\u{1F6E1}\uFE0F Normal" }[mode] || "\u26A1 Auto", inline: true }
|
|
1155
1191
|
);
|
|
1156
1192
|
if (result.session_id) {
|
|
1157
1193
|
embed.setFooter({ text: `Session: ${result.session_id}` });
|
|
@@ -1167,6 +1203,7 @@ ${displayResult}
|
|
|
1167
1203
|
} else if (detectYesNoPrompt(checkText)) {
|
|
1168
1204
|
components.push(makeYesNoButtons(sessionId));
|
|
1169
1205
|
}
|
|
1206
|
+
components.push(makeModeButtons(sessionId, mode));
|
|
1170
1207
|
components.push(makeCompletionButtons(sessionId));
|
|
1171
1208
|
await channel.send({ embeds: [embed], components });
|
|
1172
1209
|
}
|
|
@@ -1337,6 +1374,8 @@ async function handleClaude(interaction) {
|
|
|
1337
1374
|
return handleClaudeModel(interaction);
|
|
1338
1375
|
case "verbose":
|
|
1339
1376
|
return handleClaudeVerbose(interaction);
|
|
1377
|
+
case "mode":
|
|
1378
|
+
return handleClaudeMode(interaction);
|
|
1340
1379
|
default:
|
|
1341
1380
|
await interaction.reply({ content: `Unknown subcommand: ${sub}`, ephemeral: true });
|
|
1342
1381
|
}
|
|
@@ -1560,7 +1599,8 @@ async function handleClaudeList(interaction) {
|
|
|
1560
1599
|
for (const [project, projectSessions] of grouped) {
|
|
1561
1600
|
const lines = projectSessions.map((s) => {
|
|
1562
1601
|
const status = s.isGenerating ? "\u{1F7E2} generating" : "\u26AA idle";
|
|
1563
|
-
|
|
1602
|
+
const modeEmoji = { auto: "\u26A1", plan: "\u{1F4CB}", normal: "\u{1F6E1}\uFE0F" }[s.mode] || "\u26A1";
|
|
1603
|
+
return `**${s.id}** \u2014 ${status} ${modeEmoji} ${s.mode} | ${formatUptime(s.createdAt)} uptime | ${s.messageCount} msgs | $${s.totalCost.toFixed(4)} | ${formatLastActivity(s.lastActivity)}`;
|
|
1564
1604
|
});
|
|
1565
1605
|
embed.addFields({ name: `\u{1F4C1} ${project}`, value: lines.join("\n") });
|
|
1566
1606
|
}
|
|
@@ -1596,7 +1636,7 @@ async function handleClaudeContinue(interaction) {
|
|
|
1596
1636
|
const channel = interaction.channel;
|
|
1597
1637
|
const stream = continueSession(session.id);
|
|
1598
1638
|
await interaction.editReply("Continuing...");
|
|
1599
|
-
await handleOutputStream(stream, channel, session.id, session.verbose);
|
|
1639
|
+
await handleOutputStream(stream, channel, session.id, session.verbose, session.mode);
|
|
1600
1640
|
} catch (err) {
|
|
1601
1641
|
await interaction.editReply(`Error: ${err.message}`);
|
|
1602
1642
|
}
|
|
@@ -1697,6 +1737,24 @@ async function handleClaudeVerbose(interaction) {
|
|
|
1697
1737
|
ephemeral: true
|
|
1698
1738
|
});
|
|
1699
1739
|
}
|
|
1740
|
+
var MODE_LABELS = {
|
|
1741
|
+
auto: "\u26A1 Auto \u2014 full autonomy, no confirmations",
|
|
1742
|
+
plan: "\u{1F4CB} Plan \u2014 always plans before executing changes",
|
|
1743
|
+
normal: "\u{1F6E1}\uFE0F Normal \u2014 asks before destructive operations"
|
|
1744
|
+
};
|
|
1745
|
+
async function handleClaudeMode(interaction) {
|
|
1746
|
+
const session = getSessionByChannel(interaction.channelId);
|
|
1747
|
+
if (!session) {
|
|
1748
|
+
await interaction.reply({ content: "No session in this channel.", ephemeral: true });
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
const mode = interaction.options.getString("mode", true);
|
|
1752
|
+
setMode(session.id, mode);
|
|
1753
|
+
await interaction.reply({
|
|
1754
|
+
content: `Mode set to **${MODE_LABELS[mode]}**`,
|
|
1755
|
+
ephemeral: true
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1700
1758
|
async function handleShell(interaction) {
|
|
1701
1759
|
if (!isUserAllowed(interaction.user.id, config.allowedUsers, config.allowAllUsers)) {
|
|
1702
1760
|
await interaction.reply({ content: "You are not authorized.", ephemeral: true });
|
|
@@ -1860,7 +1918,7 @@ ${list}`, ephemeral: true });
|
|
|
1860
1918
|
const channel = interaction.channel;
|
|
1861
1919
|
await interaction.editReply(`Running skill **${name}**...`);
|
|
1862
1920
|
const stream = sendPrompt(session.id, expanded);
|
|
1863
|
-
await handleOutputStream(stream, channel, session.id, session.verbose);
|
|
1921
|
+
await handleOutputStream(stream, channel, session.id, session.verbose, session.mode);
|
|
1864
1922
|
} catch (err) {
|
|
1865
1923
|
await interaction.editReply(`Error: ${err.message}`);
|
|
1866
1924
|
}
|
|
@@ -1964,7 +2022,7 @@ async function handleMessage(message) {
|
|
|
1964
2022
|
try {
|
|
1965
2023
|
const channel = message.channel;
|
|
1966
2024
|
const stream = sendPrompt(session.id, content);
|
|
1967
|
-
await handleOutputStream(stream, channel, session.id, session.verbose);
|
|
2025
|
+
await handleOutputStream(stream, channel, session.id, session.verbose, session.mode);
|
|
1968
2026
|
} catch (err) {
|
|
1969
2027
|
await message.reply({
|
|
1970
2028
|
content: `Error: ${err.message}`,
|
|
@@ -2005,7 +2063,7 @@ async function handleButton(interaction) {
|
|
|
2005
2063
|
const channel = interaction.channel;
|
|
2006
2064
|
const stream = continueSession(sessionId);
|
|
2007
2065
|
await interaction.editReply("Continuing...");
|
|
2008
|
-
await handleOutputStream(stream, channel, sessionId, session.verbose);
|
|
2066
|
+
await handleOutputStream(stream, channel, sessionId, session.verbose, session.mode);
|
|
2009
2067
|
} catch (err) {
|
|
2010
2068
|
await interaction.editReply(`Error: ${err.message}`);
|
|
2011
2069
|
}
|
|
@@ -2039,7 +2097,7 @@ ${display}
|
|
|
2039
2097
|
const channel = interaction.channel;
|
|
2040
2098
|
const stream = sendPrompt(sessionId, optionText);
|
|
2041
2099
|
await interaction.editReply(`Selected option ${optionIndex + 1}`);
|
|
2042
|
-
await handleOutputStream(stream, channel, sessionId, session.verbose);
|
|
2100
|
+
await handleOutputStream(stream, channel, sessionId, session.verbose, session.mode);
|
|
2043
2101
|
} catch (err) {
|
|
2044
2102
|
await interaction.editReply(`Error: ${err.message}`);
|
|
2045
2103
|
}
|
|
@@ -2059,7 +2117,7 @@ ${display}
|
|
|
2059
2117
|
const channel = interaction.channel;
|
|
2060
2118
|
const stream = sendPrompt(sessionId, answer);
|
|
2061
2119
|
await interaction.editReply(`Answered: **${truncate(answer, 100)}**`);
|
|
2062
|
-
await handleOutputStream(stream, channel, sessionId, session.verbose);
|
|
2120
|
+
await handleOutputStream(stream, channel, sessionId, session.verbose, session.mode);
|
|
2063
2121
|
} catch (err) {
|
|
2064
2122
|
await interaction.editReply(`Error: ${err.message}`);
|
|
2065
2123
|
}
|
|
@@ -2079,12 +2137,45 @@ ${display}
|
|
|
2079
2137
|
const channel = interaction.channel;
|
|
2080
2138
|
const stream = sendPrompt(sessionId, answer);
|
|
2081
2139
|
await interaction.editReply(`Answered: ${answer}`);
|
|
2082
|
-
await handleOutputStream(stream, channel, sessionId, session.verbose);
|
|
2140
|
+
await handleOutputStream(stream, channel, sessionId, session.verbose, session.mode);
|
|
2083
2141
|
} catch (err) {
|
|
2084
2142
|
await interaction.editReply(`Error: ${err.message}`);
|
|
2085
2143
|
}
|
|
2086
2144
|
return;
|
|
2087
2145
|
}
|
|
2146
|
+
if (customId.startsWith("mode:")) {
|
|
2147
|
+
const parts = customId.split(":");
|
|
2148
|
+
const sessionId = parts[1];
|
|
2149
|
+
const newMode = parts[2];
|
|
2150
|
+
const session = getSession(sessionId);
|
|
2151
|
+
if (!session) {
|
|
2152
|
+
await interaction.reply({ content: "Session not found.", ephemeral: true });
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
setMode(sessionId, newMode);
|
|
2156
|
+
const labels = {
|
|
2157
|
+
auto: "\u26A1 Auto \u2014 full autonomy",
|
|
2158
|
+
plan: "\u{1F4CB} Plan \u2014 plans before changes",
|
|
2159
|
+
normal: "\u{1F6E1}\uFE0F Normal \u2014 asks before destructive ops"
|
|
2160
|
+
};
|
|
2161
|
+
await interaction.reply({
|
|
2162
|
+
content: `Mode switched to **${labels[newMode]}**`,
|
|
2163
|
+
ephemeral: true
|
|
2164
|
+
});
|
|
2165
|
+
try {
|
|
2166
|
+
const original = interaction.message;
|
|
2167
|
+
const updatedComponents = original.components.map((row) => {
|
|
2168
|
+
const first = row.components?.[0];
|
|
2169
|
+
if (first?.customId?.startsWith("mode:")) {
|
|
2170
|
+
return makeModeButtons(sessionId, newMode);
|
|
2171
|
+
}
|
|
2172
|
+
return row;
|
|
2173
|
+
});
|
|
2174
|
+
await original.edit({ components: updatedComponents });
|
|
2175
|
+
} catch {
|
|
2176
|
+
}
|
|
2177
|
+
return;
|
|
2178
|
+
}
|
|
2088
2179
|
await interaction.reply({ content: "Unknown button.", ephemeral: true });
|
|
2089
2180
|
}
|
|
2090
2181
|
async function handleSelectMenu(interaction) {
|
|
@@ -2106,7 +2197,7 @@ async function handleSelectMenu(interaction) {
|
|
|
2106
2197
|
const channel = interaction.channel;
|
|
2107
2198
|
const stream = sendPrompt(sessionId, selected);
|
|
2108
2199
|
await interaction.editReply(`Answered: **${truncate(selected, 100)}**`);
|
|
2109
|
-
await handleOutputStream(stream, channel, sessionId, session.verbose);
|
|
2200
|
+
await handleOutputStream(stream, channel, sessionId, session.verbose, session.mode);
|
|
2110
2201
|
} catch (err) {
|
|
2111
2202
|
await interaction.editReply(`Error: ${err.message}`);
|
|
2112
2203
|
}
|
|
@@ -2125,7 +2216,7 @@ async function handleSelectMenu(interaction) {
|
|
|
2125
2216
|
const channel = interaction.channel;
|
|
2126
2217
|
const stream = sendPrompt(sessionId, selected);
|
|
2127
2218
|
await interaction.editReply(`Selected: ${truncate(selected, 100)}`);
|
|
2128
|
-
await handleOutputStream(stream, channel, sessionId, session.verbose);
|
|
2219
|
+
await handleOutputStream(stream, channel, sessionId, session.verbose, session.mode);
|
|
2129
2220
|
} catch (err) {
|
|
2130
2221
|
await interaction.editReply(`Error: ${err.message}`);
|
|
2131
2222
|
}
|
package/dist/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ switch (command) {
|
|
|
18
18
|
console.log("Run \x1B[36magentcord setup\x1B[0m to configure.\n");
|
|
19
19
|
process.exit(1);
|
|
20
20
|
}
|
|
21
|
-
const { startBot } = await import("./bot-
|
|
21
|
+
const { startBot } = await import("./bot-G6464LRS.js");
|
|
22
22
|
console.log("agentcord starting...");
|
|
23
23
|
await startBot();
|
|
24
24
|
break;
|