refactor: route channel runtime via plugin api
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { slackPlugin } from "./src/channel.js";
|
||||
import { setSlackRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
id: "slack",
|
||||
name: "Slack",
|
||||
description: "Slack channel plugin",
|
||||
register(api: ClawdbotPluginApi) {
|
||||
setSlackRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: slackPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,28 +6,20 @@ import {
|
||||
deleteAccountFromConfigSection,
|
||||
formatPairingApproveHint,
|
||||
getChatChannelMeta,
|
||||
handleSlackAction,
|
||||
loadConfig,
|
||||
listEnabledSlackAccounts,
|
||||
listSlackAccountIds,
|
||||
listSlackDirectoryGroupsFromConfig,
|
||||
listSlackDirectoryGroupsLive,
|
||||
listSlackDirectoryPeersFromConfig,
|
||||
listSlackDirectoryPeersLive,
|
||||
looksLikeSlackTargetId,
|
||||
migrateBaseNameToDefaultAccount,
|
||||
normalizeAccountId,
|
||||
normalizeSlackMessagingTarget,
|
||||
PAIRING_APPROVED_MESSAGE,
|
||||
probeSlack,
|
||||
readNumberParam,
|
||||
readStringParam,
|
||||
resolveDefaultSlackAccountId,
|
||||
resolveSlackAccount,
|
||||
resolveSlackChannelAllowlist,
|
||||
resolveSlackGroupRequireMention,
|
||||
resolveSlackUserAllowlist,
|
||||
sendMessageSlack,
|
||||
setAccountEnabledInConfigSection,
|
||||
slackOnboardingAdapter,
|
||||
SlackConfigSchema,
|
||||
@@ -36,6 +28,8 @@ import {
|
||||
type ResolvedSlackAccount,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
|
||||
import { getSlackRuntime } from "./runtime.js";
|
||||
|
||||
const meta = getChatChannelMeta("slack");
|
||||
|
||||
// Select the appropriate Slack token for read/write operations.
|
||||
@@ -61,7 +55,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
idLabel: "slackUserId",
|
||||
normalizeAllowEntry: (entry) => entry.replace(/^(slack|user):/i, ""),
|
||||
notifyApproval: async ({ id }) => {
|
||||
const cfg = loadConfig();
|
||||
const cfg = getSlackRuntime().config.loadConfig();
|
||||
const account = resolveSlackAccount({
|
||||
cfg,
|
||||
accountId: DEFAULT_ACCOUNT_ID,
|
||||
@@ -70,11 +64,11 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
const botToken = account.botToken?.trim();
|
||||
const tokenOverride = token && token !== botToken ? token : undefined;
|
||||
if (tokenOverride) {
|
||||
await sendMessageSlack(`user:${id}`, PAIRING_APPROVED_MESSAGE, {
|
||||
await getSlackRuntime().channel.slack.sendMessageSlack(`user:${id}`, PAIRING_APPROVED_MESSAGE, {
|
||||
token: tokenOverride,
|
||||
});
|
||||
} else {
|
||||
await sendMessageSlack(`user:${id}`, PAIRING_APPROVED_MESSAGE);
|
||||
await getSlackRuntime().channel.slack.sendMessageSlack(`user:${id}`, PAIRING_APPROVED_MESSAGE);
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -194,8 +188,9 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
self: async () => null,
|
||||
listPeers: async (params) => listSlackDirectoryPeersFromConfig(params),
|
||||
listGroups: async (params) => listSlackDirectoryGroupsFromConfig(params),
|
||||
listPeersLive: async (params) => listSlackDirectoryPeersLive(params),
|
||||
listGroupsLive: async (params) => listSlackDirectoryGroupsLive(params),
|
||||
listPeersLive: async (params) => getSlackRuntime().channel.slack.listDirectoryPeersLive(params),
|
||||
listGroupsLive: async (params) =>
|
||||
getSlackRuntime().channel.slack.listDirectoryGroupsLive(params),
|
||||
},
|
||||
resolver: {
|
||||
resolveTargets: async ({ cfg, accountId, inputs, kind }) => {
|
||||
@@ -209,7 +204,10 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
}));
|
||||
}
|
||||
if (kind === "group") {
|
||||
const resolved = await resolveSlackChannelAllowlist({ token, entries: inputs });
|
||||
const resolved = await getSlackRuntime().channel.slack.resolveChannelAllowlist({
|
||||
token,
|
||||
entries: inputs,
|
||||
});
|
||||
return resolved.map((entry) => ({
|
||||
input: entry.input,
|
||||
resolved: entry.resolved,
|
||||
@@ -218,7 +216,10 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
note: entry.archived ? "archived" : undefined,
|
||||
}));
|
||||
}
|
||||
const resolved = await resolveSlackUserAllowlist({ token, entries: inputs });
|
||||
const resolved = await getSlackRuntime().channel.slack.resolveUserAllowlist({
|
||||
token,
|
||||
entries: inputs,
|
||||
});
|
||||
return resolved.map((entry) => ({
|
||||
input: entry.input,
|
||||
resolved: entry.resolved,
|
||||
@@ -284,7 +285,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
const mediaUrl = readStringParam(params, "media", { trim: false });
|
||||
const threadId = readStringParam(params, "threadId");
|
||||
const replyTo = readStringParam(params, "replyTo");
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
to,
|
||||
@@ -304,7 +305,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
});
|
||||
const emoji = readStringParam(params, "emoji", { allowEmpty: true });
|
||||
const remove = typeof params.remove === "boolean" ? params.remove : undefined;
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{
|
||||
action: "react",
|
||||
channelId: resolveChannelId(),
|
||||
@@ -322,7 +323,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
required: true,
|
||||
});
|
||||
const limit = readNumberParam(params, "limit", { integer: true });
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{
|
||||
action: "reactions",
|
||||
channelId: resolveChannelId(),
|
||||
@@ -336,7 +337,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
|
||||
if (action === "read") {
|
||||
const limit = readNumberParam(params, "limit", { integer: true });
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{
|
||||
action: "readMessages",
|
||||
channelId: resolveChannelId(),
|
||||
@@ -354,7 +355,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
required: true,
|
||||
});
|
||||
const content = readStringParam(params, "message", { required: true });
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{
|
||||
action: "editMessage",
|
||||
channelId: resolveChannelId(),
|
||||
@@ -370,7 +371,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
const messageId = readStringParam(params, "messageId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{
|
||||
action: "deleteMessage",
|
||||
channelId: resolveChannelId(),
|
||||
@@ -386,7 +387,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
action === "list-pins"
|
||||
? undefined
|
||||
: readStringParam(params, "messageId", { required: true });
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{
|
||||
action:
|
||||
action === "pin" ? "pinMessage" : action === "unpin" ? "unpinMessage" : "listPins",
|
||||
@@ -400,14 +401,14 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
|
||||
if (action === "member-info") {
|
||||
const userId = readStringParam(params, "userId", { required: true });
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{ action: "memberInfo", userId, accountId: accountId ?? undefined },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "emoji-list") {
|
||||
return await handleSlackAction(
|
||||
return await getSlackRuntime().channel.slack.handleSlackAction(
|
||||
{ action: "emojiList", accountId: accountId ?? undefined },
|
||||
cfg,
|
||||
);
|
||||
@@ -492,7 +493,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
chunker: null,
|
||||
textChunkLimit: 4000,
|
||||
sendText: async ({ to, text, accountId, deps, replyToId, cfg }) => {
|
||||
const send = deps?.sendSlack ?? sendMessageSlack;
|
||||
const send = deps?.sendSlack ?? getSlackRuntime().channel.slack.sendMessageSlack;
|
||||
const account = resolveSlackAccount({ cfg, accountId });
|
||||
const token = getTokenForOperation(account, "write");
|
||||
const botToken = account.botToken?.trim();
|
||||
@@ -505,7 +506,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
return { channel: "slack", ...result };
|
||||
},
|
||||
sendMedia: async ({ to, text, mediaUrl, accountId, deps, replyToId, cfg }) => {
|
||||
const send = deps?.sendSlack ?? sendMessageSlack;
|
||||
const send = deps?.sendSlack ?? getSlackRuntime().channel.slack.sendMessageSlack;
|
||||
const account = resolveSlackAccount({ cfg, accountId });
|
||||
const token = getTokenForOperation(account, "write");
|
||||
const botToken = account.botToken?.trim();
|
||||
@@ -541,7 +542,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
probeAccount: async ({ account, timeoutMs }) => {
|
||||
const token = account.botToken?.trim();
|
||||
if (!token) return { ok: false, error: "missing token" };
|
||||
return await probeSlack(token, timeoutMs);
|
||||
return await getSlackRuntime().channel.slack.probeSlack(token, timeoutMs);
|
||||
},
|
||||
buildAccountSnapshot: ({ account, runtime, probe }) => {
|
||||
const configured = Boolean(account.botToken && account.appToken);
|
||||
@@ -568,9 +569,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
|
||||
const botToken = account.botToken?.trim();
|
||||
const appToken = account.appToken?.trim();
|
||||
ctx.log?.info(`[${account.accountId}] starting provider`);
|
||||
// Lazy import: the monitor pulls the reply pipeline; avoid ESM init cycles.
|
||||
const { monitorSlackProvider } = await import("clawdbot/plugin-sdk");
|
||||
return monitorSlackProvider({
|
||||
return getSlackRuntime().channel.slack.monitorSlackProvider({
|
||||
botToken: botToken ?? "",
|
||||
appToken: appToken ?? "",
|
||||
accountId: account.accountId,
|
||||
|
||||
14
extensions/slack/src/runtime.ts
Normal file
14
extensions/slack/src/runtime.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
export function setSlackRuntime(next: PluginRuntime) {
|
||||
runtime = next;
|
||||
}
|
||||
|
||||
export function getSlackRuntime(): PluginRuntime {
|
||||
if (!runtime) {
|
||||
throw new Error("Slack runtime not initialized");
|
||||
}
|
||||
return runtime;
|
||||
}
|
||||
Reference in New Issue
Block a user