refactor(core): dedupe shared config and runtime helpers

This commit is contained in:
Peter Steinberger
2026-02-16 14:52:03 +00:00
parent 544ffbcf7b
commit 04892ee230
68 changed files with 1966 additions and 2018 deletions

View File

@@ -0,0 +1,162 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import type { ChannelMessageActionContext } from "../channels/plugins/types.js";
import { readNumberParam, readStringParam } from "../agents/tools/common.js";
type SlackActionInvoke = (
action: Record<string, unknown>,
cfg: ChannelMessageActionContext["cfg"],
toolContext?: ChannelMessageActionContext["toolContext"],
) => Promise<AgentToolResult<unknown>>;
export async function handleSlackMessageAction(params: {
providerId: string;
ctx: ChannelMessageActionContext;
invoke: SlackActionInvoke;
normalizeChannelId?: (channelId: string) => string;
includeReadThreadId?: boolean;
}): Promise<AgentToolResult<unknown>> {
const { providerId, ctx, invoke, normalizeChannelId, includeReadThreadId = false } = params;
const { action, cfg, params: actionParams } = ctx;
const accountId = ctx.accountId ?? undefined;
const resolveChannelId = () => {
const channelId =
readStringParam(actionParams, "channelId") ??
readStringParam(actionParams, "to", { required: true });
return normalizeChannelId ? normalizeChannelId(channelId) : channelId;
};
if (action === "send") {
const to = readStringParam(actionParams, "to", { required: true });
const content = readStringParam(actionParams, "message", {
required: true,
allowEmpty: true,
});
const mediaUrl = readStringParam(actionParams, "media", { trim: false });
const threadId = readStringParam(actionParams, "threadId");
const replyTo = readStringParam(actionParams, "replyTo");
return await invoke(
{
action: "sendMessage",
to,
content,
mediaUrl: mediaUrl ?? undefined,
accountId,
threadTs: threadId ?? replyTo ?? undefined,
},
cfg,
ctx.toolContext,
);
}
if (action === "react") {
const messageId = readStringParam(actionParams, "messageId", {
required: true,
});
const emoji = readStringParam(actionParams, "emoji", { allowEmpty: true });
const remove = typeof actionParams.remove === "boolean" ? actionParams.remove : undefined;
return await invoke(
{
action: "react",
channelId: resolveChannelId(),
messageId,
emoji,
remove,
accountId,
},
cfg,
);
}
if (action === "reactions") {
const messageId = readStringParam(actionParams, "messageId", {
required: true,
});
const limit = readNumberParam(actionParams, "limit", { integer: true });
return await invoke(
{
action: "reactions",
channelId: resolveChannelId(),
messageId,
limit,
accountId,
},
cfg,
);
}
if (action === "read") {
const limit = readNumberParam(actionParams, "limit", { integer: true });
const readAction: Record<string, unknown> = {
action: "readMessages",
channelId: resolveChannelId(),
limit,
before: readStringParam(actionParams, "before"),
after: readStringParam(actionParams, "after"),
accountId,
};
if (includeReadThreadId) {
readAction.threadId = readStringParam(actionParams, "threadId");
}
return await invoke(readAction, cfg);
}
if (action === "edit") {
const messageId = readStringParam(actionParams, "messageId", {
required: true,
});
const content = readStringParam(actionParams, "message", { required: true });
return await invoke(
{
action: "editMessage",
channelId: resolveChannelId(),
messageId,
content,
accountId,
},
cfg,
);
}
if (action === "delete") {
const messageId = readStringParam(actionParams, "messageId", {
required: true,
});
return await invoke(
{
action: "deleteMessage",
channelId: resolveChannelId(),
messageId,
accountId,
},
cfg,
);
}
if (action === "pin" || action === "unpin" || action === "list-pins") {
const messageId =
action === "list-pins"
? undefined
: readStringParam(actionParams, "messageId", { required: true });
return await invoke(
{
action: action === "pin" ? "pinMessage" : action === "unpin" ? "unpinMessage" : "listPins",
channelId: resolveChannelId(),
messageId,
accountId,
},
cfg,
);
}
if (action === "member-info") {
const userId = readStringParam(actionParams, "userId", { required: true });
return await invoke({ action: "memberInfo", userId, accountId }, cfg);
}
if (action === "emoji-list") {
const limit = readNumberParam(actionParams, "limit", { integer: true });
return await invoke({ action: "emojiList", limit, accountId }, cfg);
}
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
}