feat(discord): expose channel management actions via message tool

Add channel-create, channel-edit, channel-delete, channel-move,
category-create, category-edit, and category-delete actions to the
unified message tool. These actions were already implemented in the
Discord-specific handler but weren't accessible via the pi_message tool.

Changes:
- Add 7 new channel/category management actions to MessageActionSchema
- Add parameters: name, type, parentId, topic, position, nsfw,
  rateLimitPerUser, categoryId
- Gate actions behind discord.actions.channels (disabled by default)
- Add execute handlers routing to existing Discord action handlers
- Update Discord skill SKILL.md with documentation

Channel types: 0=text, 2=voice, 4=category
This commit is contained in:
Nicholas Spisak
2026-01-11 10:33:02 -05:00
committed by Shadow
parent 70ba369d65
commit d63eae528c
3 changed files with 240 additions and 1 deletions

View File

@@ -57,6 +57,15 @@ export const discordMessageActions: ProviderMessageActionAdapter = {
actions.add("channel-info");
actions.add("channel-list");
}
if (gate("channels", false)) {
actions.add("channel-create");
actions.add("channel-edit");
actions.add("channel-delete");
actions.add("channel-move");
actions.add("category-create");
actions.add("category-edit");
actions.add("category-delete");
}
if (gate("voiceStatus")) actions.add("voice-status");
if (gate("events")) {
actions.add("event-list");
@@ -449,6 +458,136 @@ export const discordMessageActions: ProviderMessageActionAdapter = {
return await handleDiscordAction({ action: "channelList", guildId }, cfg);
}
if (action === "channel-create") {
const guildId = readStringParam(params, "guildId", { required: true });
const name = readStringParam(params, "name", { required: true });
const type = readNumberParam(params, "type", { integer: true });
const parentId =
params.parentId === null
? null
: readStringParam(params, "parentId");
const topic = readStringParam(params, "topic");
const position = readNumberParam(params, "position", { integer: true });
const nsfw = typeof params.nsfw === "boolean" ? params.nsfw : undefined;
return await handleDiscordAction(
{
action: "channelCreate",
guildId,
name,
type: type ?? undefined,
parentId: parentId ?? undefined,
topic: topic ?? undefined,
position: position ?? undefined,
nsfw,
},
cfg,
);
}
if (action === "channel-edit") {
const channelId = readStringParam(params, "channelId", {
required: true,
});
const name = readStringParam(params, "name");
const topic = readStringParam(params, "topic");
const position = readNumberParam(params, "position", { integer: true });
const parentId =
params.parentId === null
? null
: readStringParam(params, "parentId");
const nsfw = typeof params.nsfw === "boolean" ? params.nsfw : undefined;
const rateLimitPerUser = readNumberParam(params, "rateLimitPerUser", {
integer: true,
});
return await handleDiscordAction(
{
action: "channelEdit",
channelId,
name: name ?? undefined,
topic: topic ?? undefined,
position: position ?? undefined,
parentId: parentId === undefined ? undefined : parentId,
nsfw,
rateLimitPerUser: rateLimitPerUser ?? undefined,
},
cfg,
);
}
if (action === "channel-delete") {
const channelId = readStringParam(params, "channelId", {
required: true,
});
return await handleDiscordAction(
{ action: "channelDelete", channelId },
cfg,
);
}
if (action === "channel-move") {
const guildId = readStringParam(params, "guildId", { required: true });
const channelId = readStringParam(params, "channelId", {
required: true,
});
const parentId =
params.parentId === null
? null
: readStringParam(params, "parentId");
const position = readNumberParam(params, "position", { integer: true });
return await handleDiscordAction(
{
action: "channelMove",
guildId,
channelId,
parentId: parentId === undefined ? undefined : parentId,
position: position ?? undefined,
},
cfg,
);
}
if (action === "category-create") {
const guildId = readStringParam(params, "guildId", { required: true });
const name = readStringParam(params, "name", { required: true });
const position = readNumberParam(params, "position", { integer: true });
return await handleDiscordAction(
{
action: "categoryCreate",
guildId,
name,
position: position ?? undefined,
},
cfg,
);
}
if (action === "category-edit") {
const categoryId = readStringParam(params, "categoryId", {
required: true,
});
const name = readStringParam(params, "name");
const position = readNumberParam(params, "position", { integer: true });
return await handleDiscordAction(
{
action: "categoryEdit",
categoryId,
name: name ?? undefined,
position: position ?? undefined,
},
cfg,
);
}
if (action === "category-delete") {
const categoryId = readStringParam(params, "categoryId", {
required: true,
});
return await handleDiscordAction(
{ action: "categoryDelete", categoryId },
cfg,
);
}
if (action === "voice-status") {
const guildId = readStringParam(params, "guildId", {
required: true,