disclaw/src/commands/new-agent.ts
Nick Tabeling 69e0b7d727 initial
2026-04-08 14:21:19 +02:00

94 lines
2.8 KiB
TypeScript

import {
ChatInputCommandInteraction,
ChannelType,
SlashCommandBuilder,
Guild,
} from "discord.js";
import * as path from "path";
import { DisclawDatabase } from "../db/database";
import { DisclawConfig } from "../config/loader";
import { setupAgentWorkspace } from "../agent/identity";
// Allowed characters for agent names: lowercase letters, numbers, hyphens
const NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,30}[a-z0-9]$/;
export const newAgentCommand = new SlashCommandBuilder()
.setName("new-agent")
.setDescription("Erstellt einen neuen Agenten mit eigenem Kanal und Workspace")
.addStringOption((option) =>
option
.setName("name")
.setDescription("Eindeutiger Name fuer den Agenten (z.B. frontend-dev)")
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("role")
.setDescription("Rolle des Agenten (z.B. Frontend-Entwickler)")
.setRequired(true)
);
export async function handleNewAgent(
interaction: ChatInputCommandInteraction,
db: DisclawDatabase,
config: DisclawConfig
): Promise<void> {
const name = interaction.options.getString("name", true).toLowerCase();
const role = interaction.options.getString("role", true);
const guild = interaction.guild as Guild;
// Validate name format
if (!NAME_PATTERN.test(name)) {
await interaction.reply({
content:
"Ungueltiger Name. Erlaubt sind Kleinbuchstaben, Zahlen und Bindestriche. " +
"Mindestens 2 Zeichen, muss mit Buchstabe oder Zahl beginnen und enden.",
ephemeral: true,
});
return;
}
// Check uniqueness
if (db.getWorkspaceByName(name)) {
await interaction.reply({
content: `Ein Agent mit dem Namen **${name}** existiert bereits.`,
ephemeral: true,
});
return;
}
await interaction.deferReply();
try {
// 1. Create Discord channel
const channel = await guild.channels.create({
name,
type: ChannelType.GuildText,
topic: `Agent: ${name} | Rolle: ${role}`,
});
// 2. Create workspace with full Claude Code environment
const workspacePath = path.resolve(config.workspaces_root, name);
setupAgentWorkspace(workspacePath, name, role, channel.id);
// 3. Save to database
db.createWorkspace(channel.id, guild.id, name, workspacePath);
// 4. Reply with confirmation
await interaction.editReply(
`Agent **${name}** erstellt in <#${channel.id}>.\n` +
`Rolle: ${role}\n` +
`Workspace: \`${workspacePath}\``
);
// 5. Send welcome message in the new channel
await channel.send(
`Hallo! Ich bin **${name}** (${role}).\n` +
`Schreib mir eine Nachricht und ich antworte dir.`
);
} catch (error) {
const msg =
error instanceof Error ? error.message : "Unbekannter Fehler";
await interaction.editReply(`Fehler beim Erstellen des Agenten: ${msg}`);
}
}