refactor!: rename chat providers to channels
This commit is contained in:
@@ -30,7 +30,7 @@ export type ResolvedSlackAccount = {
|
||||
};
|
||||
|
||||
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
const accounts = cfg.slack?.accounts;
|
||||
const accounts = cfg.channels?.slack?.accounts;
|
||||
if (!accounts || typeof accounts !== "object") return [];
|
||||
return Object.keys(accounts).filter(Boolean);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ function resolveAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
accountId: string,
|
||||
): SlackAccountConfig | undefined {
|
||||
const accounts = cfg.slack?.accounts;
|
||||
const accounts = cfg.channels?.slack?.accounts;
|
||||
if (!accounts || typeof accounts !== "object") return undefined;
|
||||
return accounts[accountId] as SlackAccountConfig | undefined;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ function mergeSlackAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
accountId: string,
|
||||
): SlackAccountConfig {
|
||||
const { accounts: _ignored, ...base } = (cfg.slack ??
|
||||
const { accounts: _ignored, ...base } = (cfg.channels?.slack ??
|
||||
{}) as SlackAccountConfig & { accounts?: unknown };
|
||||
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
||||
return { ...base, ...account };
|
||||
@@ -71,7 +71,7 @@ export function resolveSlackAccount(params: {
|
||||
accountId?: string | null;
|
||||
}): ResolvedSlackAccount {
|
||||
const accountId = normalizeAccountId(params.accountId);
|
||||
const baseEnabled = params.cfg.slack?.enabled !== false;
|
||||
const baseEnabled = params.cfg.channels?.slack?.enabled !== false;
|
||||
const merged = mergeSlackAccountConfig(params.cfg, accountId);
|
||||
const accountEnabled = merged.enabled !== false;
|
||||
const enabled = baseEnabled && accountEnabled;
|
||||
|
||||
@@ -42,7 +42,7 @@ function resolveToken(explicit?: string, accountId?: string) {
|
||||
)} source=${account.botTokenSource ?? "unknown"}`,
|
||||
);
|
||||
throw new Error(
|
||||
"SLACK_BOT_TOKEN or slack.botToken is required for Slack actions",
|
||||
"SLACK_BOT_TOKEN or channels.slack.botToken is required for Slack actions",
|
||||
);
|
||||
}
|
||||
return token;
|
||||
|
||||
@@ -38,9 +38,9 @@ vi.mock("./send.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../pairing/pairing-store.js", () => ({
|
||||
readProviderAllowFromStore: (...args: unknown[]) =>
|
||||
readChannelAllowFromStore: (...args: unknown[]) =>
|
||||
readAllowFromStoreMock(...args),
|
||||
upsertProviderPairingRequest: (...args: unknown[]) =>
|
||||
upsertChannelPairingRequest: (...args: unknown[]) =>
|
||||
upsertPairingRequestMock(...args),
|
||||
}));
|
||||
|
||||
@@ -108,9 +108,11 @@ beforeEach(() => {
|
||||
ackReaction: "👀",
|
||||
ackReactionScope: "group-mentions",
|
||||
},
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
groupPolicy: "open",
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
groupPolicy: "open",
|
||||
},
|
||||
},
|
||||
};
|
||||
sendMock.mockReset().mockResolvedValue(undefined);
|
||||
@@ -179,14 +181,16 @@ describe("monitorSlackProvider tool results", () => {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "rich",
|
||||
match: { provider: "slack", peer: { kind: "dm", id: "U1" } },
|
||||
match: { channel: "slack", peer: { kind: "dm", id: "U1" } },
|
||||
},
|
||||
],
|
||||
messages: {
|
||||
ackReaction: "👀",
|
||||
ackReactionScope: "group-mentions",
|
||||
},
|
||||
slack: { dm: { enabled: true, policy: "open", allowFrom: ["*"] } },
|
||||
channels: {
|
||||
slack: { dm: { enabled: true, policy: "open", allowFrom: ["*"] } },
|
||||
},
|
||||
};
|
||||
|
||||
replyMock.mockImplementation(async (_ctx, opts) => {
|
||||
@@ -228,10 +232,12 @@ describe("monitorSlackProvider tool results", () => {
|
||||
it("wraps room history in Body and preserves RawBody", async () => {
|
||||
config = {
|
||||
messages: { ackReactionScope: "group-mentions" },
|
||||
slack: {
|
||||
historyLimit: 5,
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { "*": { requireMention: false } },
|
||||
channels: {
|
||||
slack: {
|
||||
historyLimit: 5,
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { "*": { requireMention: false } },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -344,9 +350,11 @@ describe("monitorSlackProvider tool results", () => {
|
||||
responsePrefix: "PFX",
|
||||
groupChat: { mentionPatterns: ["\\bclawd\\b"] },
|
||||
},
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { C1: { allow: true, requireMention: true } },
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { C1: { allow: true, requireMention: true } },
|
||||
},
|
||||
},
|
||||
};
|
||||
replyMock.mockResolvedValue({ text: "hi" });
|
||||
@@ -422,9 +430,11 @@ describe("monitorSlackProvider tool results", () => {
|
||||
ackReaction: "👀",
|
||||
ackReactionScope: "group-mentions",
|
||||
},
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "off",
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "off",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -467,9 +477,11 @@ describe("monitorSlackProvider tool results", () => {
|
||||
ackReaction: "👀",
|
||||
ackReactionScope: "group-mentions",
|
||||
},
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "all",
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "all",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -560,9 +572,11 @@ describe("monitorSlackProvider tool results", () => {
|
||||
|
||||
config = {
|
||||
messages: { responsePrefix: "PFX" },
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { C1: { allow: true, requireMention: false } },
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { C1: { allow: true, requireMention: false } },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -610,12 +624,14 @@ describe("monitorSlackProvider tool results", () => {
|
||||
replyMock.mockResolvedValue({ text: "ok" });
|
||||
config = {
|
||||
messages: { responsePrefix: "PFX" },
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { C1: { allow: true, requireMention: false } },
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
channels: { C1: { allow: true, requireMention: false } },
|
||||
},
|
||||
},
|
||||
bindings: [
|
||||
{ agentId: "support", match: { provider: "slack", teamId: "T1" } },
|
||||
{ agentId: "support", match: { channel: "slack", teamId: "T1" } },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -678,9 +694,11 @@ describe("monitorSlackProvider tool results", () => {
|
||||
ackReaction: "👀",
|
||||
ackReactionScope: "group-mentions",
|
||||
},
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "off",
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "off",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -722,9 +740,11 @@ describe("monitorSlackProvider tool results", () => {
|
||||
ackReaction: "👀",
|
||||
ackReactionScope: "group-mentions",
|
||||
},
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "first",
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "first",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -767,9 +787,11 @@ describe("monitorSlackProvider tool results", () => {
|
||||
ackReaction: "👀",
|
||||
ackReactionScope: "group-mentions",
|
||||
},
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "off",
|
||||
channels: {
|
||||
slack: {
|
||||
dm: { enabled: true, policy: "open", allowFrom: ["*"] },
|
||||
replyToMode: "off",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -850,7 +872,13 @@ describe("monitorSlackProvider tool results", () => {
|
||||
it("replies with pairing code when dmPolicy is pairing and no allowFrom is set", async () => {
|
||||
config = {
|
||||
...config,
|
||||
slack: { dm: { enabled: true, policy: "pairing", allowFrom: [] } },
|
||||
channels: {
|
||||
...config.channels,
|
||||
slack: {
|
||||
...config.channels?.slack,
|
||||
dm: { enabled: true, policy: "pairing", allowFrom: [] },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const controller = new AbortController();
|
||||
@@ -893,7 +921,13 @@ describe("monitorSlackProvider tool results", () => {
|
||||
it("does not resend pairing code when a request is already pending", async () => {
|
||||
config = {
|
||||
...config,
|
||||
slack: { dm: { enabled: true, policy: "pairing", allowFrom: [] } },
|
||||
channels: {
|
||||
...config.channels,
|
||||
slack: {
|
||||
...config.channels?.slack,
|
||||
dm: { enabled: true, policy: "pairing", allowFrom: [] },
|
||||
},
|
||||
},
|
||||
};
|
||||
upsertPairingRequestMock
|
||||
.mockResolvedValueOnce({ code: "PAIRCODE", created: true })
|
||||
|
||||
@@ -59,8 +59,8 @@ import { type FetchLike, fetchRemoteMedia } from "../media/fetch.js";
|
||||
import { saveMediaBuffer } from "../media/store.js";
|
||||
import { buildPairingReply } from "../pairing/pairing-messages.js";
|
||||
import {
|
||||
readProviderAllowFromStore,
|
||||
upsertProviderPairingRequest,
|
||||
readChannelAllowFromStore,
|
||||
upsertChannelPairingRequest,
|
||||
} from "../pairing/pairing-store.js";
|
||||
import { resolveAgentRoute } from "../routing/resolve-route.js";
|
||||
import {
|
||||
@@ -488,7 +488,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
const appToken = resolveSlackAppToken(opts.appToken ?? account.appToken);
|
||||
if (!botToken || !appToken) {
|
||||
throw new Error(
|
||||
`Slack bot + app tokens missing for account "${account.accountId}" (set slack.accounts.${account.accountId}.botToken/appToken or SLACK_BOT_TOKEN/SLACK_APP_TOKEN for default).`,
|
||||
`Slack bot + app tokens missing for account "${account.accountId}" (set channels.slack.accounts.${account.accountId}.botToken/appToken or SLACK_BOT_TOKEN/SLACK_APP_TOKEN for default).`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -745,7 +745,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
const allowBots =
|
||||
channelConfig?.allowBots ??
|
||||
account.config?.allowBots ??
|
||||
cfg.slack?.allowBots ??
|
||||
cfg.channels?.slack?.allowBots ??
|
||||
false;
|
||||
const isBotMessage = Boolean(message.bot_id);
|
||||
if (isBotMessage) {
|
||||
@@ -779,7 +779,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
return;
|
||||
}
|
||||
|
||||
const storeAllowFrom = await readProviderAllowFromStore("slack").catch(
|
||||
const storeAllowFrom = await readChannelAllowFromStore("slack").catch(
|
||||
() => [],
|
||||
);
|
||||
const effectiveAllowFrom = normalizeAllowList([
|
||||
@@ -807,8 +807,8 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
if (dmPolicy === "pairing") {
|
||||
const sender = await resolveUserName(directUserId);
|
||||
const senderName = sender?.name ?? undefined;
|
||||
const { code, created } = await upsertProviderPairingRequest({
|
||||
provider: "slack",
|
||||
const { code, created } = await upsertChannelPairingRequest({
|
||||
channel: "slack",
|
||||
id: directUserId,
|
||||
meta: { name: senderName },
|
||||
});
|
||||
@@ -820,7 +820,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
await sendMessageSlack(
|
||||
message.channel,
|
||||
buildPairingReply({
|
||||
provider: "slack",
|
||||
channel: "slack",
|
||||
idLine: `Your Slack user id: ${directUserId}`,
|
||||
code,
|
||||
}),
|
||||
@@ -848,7 +848,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
provider: "slack",
|
||||
channel: "slack",
|
||||
accountId: account.accountId,
|
||||
teamId: teamId || undefined,
|
||||
peer: {
|
||||
@@ -1012,7 +1012,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
|
||||
const textWithId = `${rawBody}\n[slack message id: ${message.ts} channel: ${message.channel}]`;
|
||||
const body = formatAgentEnvelope({
|
||||
provider: "Slack",
|
||||
channel: "Slack",
|
||||
from: senderName,
|
||||
timestamp: message.ts ? Math.round(Number(message.ts) * 1000) : undefined,
|
||||
body: textWithId,
|
||||
@@ -1028,7 +1028,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
currentMessage: combinedBody,
|
||||
formatEntry: (entry) =>
|
||||
formatAgentEnvelope({
|
||||
provider: "Slack",
|
||||
channel: "Slack",
|
||||
from: roomLabel,
|
||||
timestamp: entry.timestamp,
|
||||
body: `${entry.sender}: ${entry.body}${
|
||||
@@ -1068,7 +1068,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
const starterName = starterUser?.name ?? starter.userId ?? "Unknown";
|
||||
const starterWithId = `${starter.text}\n[slack message id: ${starter.ts ?? threadTs} channel: ${message.channel}]`;
|
||||
threadStarterBody = formatThreadStarterEnvelope({
|
||||
provider: "Slack",
|
||||
channel: "Slack",
|
||||
author: starterName,
|
||||
timestamp: starter.ts
|
||||
? Math.round(Number(starter.ts) * 1000)
|
||||
@@ -1126,7 +1126,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
await updateLastRoute({
|
||||
storePath,
|
||||
sessionKey: route.mainSessionKey,
|
||||
provider: "slack",
|
||||
channel: "slack",
|
||||
to: `user:${message.user}`,
|
||||
accountId: route.accountId,
|
||||
});
|
||||
@@ -1771,7 +1771,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
const storeAllowFrom = await readProviderAllowFromStore("slack").catch(
|
||||
const storeAllowFrom = await readChannelAllowFromStore("slack").catch(
|
||||
() => [],
|
||||
);
|
||||
const effectiveAllowFrom = normalizeAllowList([
|
||||
@@ -1801,15 +1801,15 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
});
|
||||
if (!permitted) {
|
||||
if (dmPolicy === "pairing") {
|
||||
const { code, created } = await upsertProviderPairingRequest({
|
||||
provider: "slack",
|
||||
const { code, created } = await upsertChannelPairingRequest({
|
||||
channel: "slack",
|
||||
id: command.user_id,
|
||||
meta: { name: senderName },
|
||||
});
|
||||
if (created) {
|
||||
await respond({
|
||||
text: buildPairingReply({
|
||||
provider: "slack",
|
||||
channel: "slack",
|
||||
idLine: `Your Slack user id: ${command.user_id}`,
|
||||
code,
|
||||
}),
|
||||
@@ -1882,7 +1882,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
const isRoomish = isRoom || isGroupDm;
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
provider: "slack",
|
||||
channel: "slack",
|
||||
accountId: account.accountId,
|
||||
teamId: teamId || undefined,
|
||||
peer: {
|
||||
|
||||
@@ -53,7 +53,7 @@ function resolveToken(params: {
|
||||
)} source=${params.fallbackSource ?? "unknown"}`,
|
||||
);
|
||||
throw new Error(
|
||||
`Slack bot token missing for account "${params.accountId}" (set slack.accounts.${params.accountId}.botToken or SLACK_BOT_TOKEN for default).`,
|
||||
`Slack bot token missing for account "${params.accountId}" (set channels.slack.accounts.${params.accountId}.botToken or SLACK_BOT_TOKEN for default).`,
|
||||
);
|
||||
}
|
||||
return fallback;
|
||||
|
||||
Reference in New Issue
Block a user