refactor!: rename chat providers to channels

This commit is contained in:
Peter Steinberger
2026-01-13 06:16:43 +00:00
parent 0cd632ba84
commit 90342a4f3a
393 changed files with 8004 additions and 6737 deletions

View File

@@ -8,7 +8,7 @@ describe("resolveAgentRoute", () => {
const cfg: ClawdbotConfig = {};
const route = resolveAgentRoute({
cfg,
provider: "whatsapp",
channel: "whatsapp",
accountId: null,
peer: { kind: "dm", id: "+15551234567" },
});
@@ -24,20 +24,20 @@ describe("resolveAgentRoute", () => {
{
agentId: "a",
match: {
provider: "whatsapp",
channel: "whatsapp",
accountId: "biz",
peer: { kind: "dm", id: "+1000" },
},
},
{
agentId: "b",
match: { provider: "whatsapp", accountId: "biz" },
match: { channel: "whatsapp", accountId: "biz" },
},
],
};
const route = resolveAgentRoute({
cfg,
provider: "whatsapp",
channel: "whatsapp",
accountId: "biz",
peer: { kind: "dm", id: "+1000" },
});
@@ -52,7 +52,7 @@ describe("resolveAgentRoute", () => {
{
agentId: "chan",
match: {
provider: "discord",
channel: "discord",
accountId: "default",
peer: { kind: "channel", id: "c1" },
},
@@ -60,7 +60,7 @@ describe("resolveAgentRoute", () => {
{
agentId: "guild",
match: {
provider: "discord",
channel: "discord",
accountId: "default",
guildId: "g1",
},
@@ -69,7 +69,7 @@ describe("resolveAgentRoute", () => {
};
const route = resolveAgentRoute({
cfg,
provider: "discord",
channel: "discord",
accountId: "default",
peer: { kind: "channel", id: "c1" },
guildId: "g1",
@@ -85,20 +85,20 @@ describe("resolveAgentRoute", () => {
{
agentId: "guild",
match: {
provider: "discord",
channel: "discord",
accountId: "default",
guildId: "g1",
},
},
{
agentId: "acct",
match: { provider: "discord", accountId: "default" },
match: { channel: "discord", accountId: "default" },
},
],
};
const route = resolveAgentRoute({
cfg,
provider: "discord",
channel: "discord",
accountId: "default",
peer: { kind: "channel", id: "c1" },
guildId: "g1",
@@ -109,12 +109,12 @@ describe("resolveAgentRoute", () => {
test("missing accountId in binding matches default account only", () => {
const cfg: ClawdbotConfig = {
bindings: [{ agentId: "defaultAcct", match: { provider: "whatsapp" } }],
bindings: [{ agentId: "defaultAcct", match: { channel: "whatsapp" } }],
};
const defaultRoute = resolveAgentRoute({
cfg,
provider: "whatsapp",
channel: "whatsapp",
accountId: undefined,
peer: { kind: "dm", id: "+1000" },
});
@@ -123,30 +123,30 @@ describe("resolveAgentRoute", () => {
const otherRoute = resolveAgentRoute({
cfg,
provider: "whatsapp",
channel: "whatsapp",
accountId: "biz",
peer: { kind: "dm", id: "+1000" },
});
expect(otherRoute.agentId).toBe("main");
});
test("accountId=* matches any account as a provider fallback", () => {
test("accountId=* matches any account as a channel fallback", () => {
const cfg: ClawdbotConfig = {
bindings: [
{
agentId: "any",
match: { provider: "whatsapp", accountId: "*" },
match: { channel: "whatsapp", accountId: "*" },
},
],
};
const route = resolveAgentRoute({
cfg,
provider: "whatsapp",
channel: "whatsapp",
accountId: "biz",
peer: { kind: "dm", id: "+1000" },
});
expect(route.agentId).toBe("any");
expect(route.matchedBy).toBe("binding.provider");
expect(route.matchedBy).toBe("binding.channel");
});
test("defaultAgentId is used when no binding matches", () => {
@@ -157,7 +157,7 @@ describe("resolveAgentRoute", () => {
};
const route = resolveAgentRoute({
cfg,
provider: "whatsapp",
channel: "whatsapp",
accountId: "biz",
peer: { kind: "dm", id: "+1000" },
});

View File

@@ -17,7 +17,7 @@ export type RoutePeer = {
export type ResolveAgentRouteInput = {
cfg: ClawdbotConfig;
provider: string;
channel: string;
accountId?: string | null;
peer?: RoutePeer | null;
guildId?: string | null;
@@ -26,7 +26,7 @@ export type ResolveAgentRouteInput = {
export type ResolvedAgentRoute = {
agentId: string;
provider: string;
channel: string;
accountId: string;
/** Internal session key used for persistence + concurrency. */
sessionKey: string;
@@ -38,7 +38,7 @@ export type ResolvedAgentRoute = {
| "binding.guild"
| "binding.team"
| "binding.account"
| "binding.provider"
| "binding.channel"
| "default";
};
@@ -66,15 +66,15 @@ function matchesAccountId(match: string | undefined, actual: string): boolean {
export function buildAgentSessionKey(params: {
agentId: string;
provider: string;
channel: string;
peer?: RoutePeer | null;
}): string {
const provider = normalizeToken(params.provider) || "unknown";
const channel = normalizeToken(params.channel) || "unknown";
const peer = params.peer;
return buildAgentPeerSessionKey({
agentId: params.agentId,
mainKey: DEFAULT_MAIN_KEY,
provider,
channel,
peerKind: peer?.kind ?? "dm",
peerId: peer ? normalizeId(peer.id) || "unknown" : null,
});
@@ -103,13 +103,13 @@ function pickFirstExistingAgentId(
return normalizeAgentId(resolveDefaultAgentId(cfg));
}
function matchesProvider(
match: { provider?: string | undefined } | undefined,
provider: string,
function matchesChannel(
match: { channel?: string | undefined } | undefined,
channel: string,
): boolean {
const key = normalizeToken(match?.provider);
const key = normalizeToken(match?.channel);
if (!key) return false;
return key === provider;
return key === channel;
}
function matchesPeer(
@@ -145,7 +145,7 @@ function matchesTeam(
export function resolveAgentRoute(
input: ResolveAgentRouteInput,
): ResolvedAgentRoute {
const provider = normalizeToken(input.provider);
const channel = normalizeToken(input.channel);
const accountId = normalizeAccountId(input.accountId);
const peer = input.peer
? { kind: input.peer.kind, id: normalizeId(input.peer.id) }
@@ -155,7 +155,7 @@ export function resolveAgentRoute(
const bindings = listBindings(input.cfg).filter((binding) => {
if (!binding || typeof binding !== "object") return false;
if (!matchesProvider(binding.match, provider)) return false;
if (!matchesChannel(binding.match, channel)) return false;
return matchesAccountId(binding.match?.accountId, accountId);
});
@@ -166,11 +166,11 @@ export function resolveAgentRoute(
const resolvedAgentId = pickFirstExistingAgentId(input.cfg, agentId);
return {
agentId: resolvedAgentId,
provider,
channel,
accountId,
sessionKey: buildAgentSessionKey({
agentId: resolvedAgentId,
provider,
channel,
peer,
}),
mainSessionKey: buildAgentMainSessionKey({
@@ -213,7 +213,7 @@ export function resolveAgentRoute(
!b.match?.teamId,
);
if (anyAccountMatch)
return choose(anyAccountMatch.agentId, "binding.provider");
return choose(anyAccountMatch.agentId, "binding.channel");
return choose(resolveDefaultAgentId(input.cfg), "default");
}

View File

@@ -89,7 +89,7 @@ export function buildAgentMainSessionKey(params: {
export function buildAgentPeerSessionKey(params: {
agentId: string;
mainKey?: string | undefined;
provider: string;
channel: string;
peerKind?: "dm" | "group" | "channel" | null;
peerId?: string | null;
}): string {
@@ -100,21 +100,21 @@ export function buildAgentPeerSessionKey(params: {
mainKey: params.mainKey,
});
}
const provider = (params.provider ?? "").trim().toLowerCase() || "unknown";
const channel = (params.channel ?? "").trim().toLowerCase() || "unknown";
const peerId = (params.peerId ?? "").trim() || "unknown";
return `agent:${normalizeAgentId(params.agentId)}:${provider}:${peerKind}:${peerId}`;
return `agent:${normalizeAgentId(params.agentId)}:${channel}:${peerKind}:${peerId}`;
}
export function buildGroupHistoryKey(params: {
provider: string;
channel: string;
accountId?: string | null;
peerKind: "group" | "channel";
peerId: string;
}): string {
const provider = normalizeToken(params.provider) || "unknown";
const channel = normalizeToken(params.channel) || "unknown";
const accountId = normalizeAccountId(params.accountId);
const peerId = params.peerId.trim() || "unknown";
return `${provider}:${accountId}:${params.peerKind}:${peerId}`;
return `${channel}:${accountId}:${params.peerKind}:${peerId}`;
}
export function resolveThreadSessionKeys(params: {