mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 04:11:22 +00:00
feat: IRC — add first-class channel support
Adds IRC as a first-class channel with core config surfaces (schema/hints/dock), plugin auto-enable detection, routing/policy alignment, and docs/tests. Co-authored-by: Vignesh <vigneshnatarajan92@gmail.com>
This commit is contained in:
@@ -10,6 +10,10 @@ import type {
|
||||
ChannelPlugin,
|
||||
ChannelThreadingAdapter,
|
||||
} from "./plugins/types.js";
|
||||
import {
|
||||
resolveChannelGroupRequireMention,
|
||||
resolveChannelGroupToolsPolicy,
|
||||
} from "../config/group-policy.js";
|
||||
import { resolveDiscordAccount } from "../discord/accounts.js";
|
||||
import { resolveIMessageAccount } from "../imessage/accounts.js";
|
||||
import { requireActivePluginRegistry } from "../plugins/runtime.js";
|
||||
@@ -75,7 +79,6 @@ const formatLower = (allowFrom: Array<string | number>) =>
|
||||
.map((entry) => String(entry).trim())
|
||||
.filter(Boolean)
|
||||
.map((entry) => entry.toLowerCase());
|
||||
|
||||
// Channel docks: lightweight channel metadata/behavior for shared code paths.
|
||||
//
|
||||
// Rules:
|
||||
@@ -213,6 +216,73 @@ const DOCKS: Record<ChatChannelId, ChannelDock> = {
|
||||
}),
|
||||
},
|
||||
},
|
||||
irc: {
|
||||
id: "irc",
|
||||
capabilities: {
|
||||
chatTypes: ["direct", "group"],
|
||||
media: true,
|
||||
blockStreaming: true,
|
||||
},
|
||||
outbound: { textChunkLimit: 350 },
|
||||
streaming: {
|
||||
blockStreamingCoalesceDefaults: { minChars: 300, idleMs: 1000 },
|
||||
},
|
||||
config: {
|
||||
resolveAllowFrom: ({ cfg, accountId }) => {
|
||||
const channel = cfg.channels?.irc;
|
||||
const normalized = normalizeAccountId(accountId);
|
||||
const account =
|
||||
channel?.accounts?.[normalized] ??
|
||||
channel?.accounts?.[
|
||||
Object.keys(channel?.accounts ?? {}).find(
|
||||
(key) => key.toLowerCase() === normalized.toLowerCase(),
|
||||
) ?? ""
|
||||
];
|
||||
return (account?.allowFrom ?? channel?.allowFrom ?? []).map((entry) => String(entry));
|
||||
},
|
||||
formatAllowFrom: ({ allowFrom }) =>
|
||||
allowFrom
|
||||
.map((entry) => String(entry).trim())
|
||||
.filter(Boolean)
|
||||
.map((entry) =>
|
||||
entry
|
||||
.replace(/^irc:/i, "")
|
||||
.replace(/^user:/i, "")
|
||||
.toLowerCase(),
|
||||
),
|
||||
},
|
||||
groups: {
|
||||
resolveRequireMention: ({ cfg, accountId, groupId }) => {
|
||||
if (!groupId) {
|
||||
return true;
|
||||
}
|
||||
return resolveChannelGroupRequireMention({
|
||||
cfg,
|
||||
channel: "irc",
|
||||
groupId,
|
||||
accountId,
|
||||
groupIdCaseInsensitive: true,
|
||||
});
|
||||
},
|
||||
resolveToolPolicy: ({ cfg, accountId, groupId, senderId, senderName, senderUsername }) => {
|
||||
if (!groupId) {
|
||||
return undefined;
|
||||
}
|
||||
// IRC supports per-channel tool policies. Prefer the shared resolver so
|
||||
// toolsBySender is honored consistently across surfaces.
|
||||
return resolveChannelGroupToolsPolicy({
|
||||
cfg,
|
||||
channel: "irc",
|
||||
groupId,
|
||||
accountId,
|
||||
groupIdCaseInsensitive: true,
|
||||
senderId,
|
||||
senderName,
|
||||
senderUsername,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
googlechat: {
|
||||
id: "googlechat",
|
||||
capabilities: {
|
||||
|
||||
@@ -10,6 +10,7 @@ describe("channel registry", () => {
|
||||
expect(normalizeChatChannelId("imsg")).toBe("imessage");
|
||||
expect(normalizeChatChannelId("gchat")).toBe("googlechat");
|
||||
expect(normalizeChatChannelId("google-chat")).toBe("googlechat");
|
||||
expect(normalizeChatChannelId("internet-relay-chat")).toBe("irc");
|
||||
expect(normalizeChatChannelId("web")).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ export const CHAT_CHANNEL_ORDER = [
|
||||
"telegram",
|
||||
"whatsapp",
|
||||
"discord",
|
||||
"irc",
|
||||
"googlechat",
|
||||
"slack",
|
||||
"signal",
|
||||
@@ -58,6 +59,16 @@ const CHAT_CHANNEL_META: Record<ChatChannelId, ChannelMeta> = {
|
||||
blurb: "very well supported right now.",
|
||||
systemImage: "bubble.left.and.bubble.right",
|
||||
},
|
||||
irc: {
|
||||
id: "irc",
|
||||
label: "IRC",
|
||||
selectionLabel: "IRC (Server + Nick)",
|
||||
detailLabel: "IRC",
|
||||
docsPath: "/channels/irc",
|
||||
docsLabel: "irc",
|
||||
blurb: "classic IRC networks with DM/channel routing and pairing controls.",
|
||||
systemImage: "network",
|
||||
},
|
||||
googlechat: {
|
||||
id: "googlechat",
|
||||
label: "Google Chat",
|
||||
@@ -102,6 +113,7 @@ const CHAT_CHANNEL_META: Record<ChatChannelId, ChannelMeta> = {
|
||||
|
||||
export const CHAT_CHANNEL_ALIASES: Record<string, ChatChannelId> = {
|
||||
imsg: "imessage",
|
||||
"internet-relay-chat": "irc",
|
||||
"google-chat": "googlechat",
|
||||
gchat: "googlechat",
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user