@openclaw/irc 2026.7.2-beta.7 → 2026.8.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +1 -1
- package/dist/{channel-DoavT7vs.js → channel-Bfg9kJRw.js} +14 -10
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-runtime-DsN_0hPp.js → channel-runtime-kWMtRD4g.js} +42 -15
- package/dist/{config-schema-BPoye3--.js → config-schema-DdB_h5mL.js} +1 -0
- package/dist/doctor-contract-api.js +1 -1
- package/openclaw.plugin.json +9 -0
- package/package.json +9 -5
package/dist/api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { _ as resolveDefaultIrcAccountId, g as listIrcAccountIds, h as listEnabledIrcAccounts, n as ircSetupWizard, r as ircSetupAdapter, t as ircPlugin, v as resolveIrcAccount } from "./channel-
|
|
1
|
+
import { _ as resolveDefaultIrcAccountId, g as listIrcAccountIds, h as listEnabledIrcAccounts, n as ircSetupWizard, r as ircSetupAdapter, t as ircPlugin, v as resolveIrcAccount } from "./channel-Bfg9kJRw.js";
|
|
2
2
|
import { n as setIrcRuntime } from "./runtime-xy-FcjJC.js";
|
|
3
3
|
export { ircPlugin, ircSetupAdapter, ircSetupWizard, listEnabledIrcAccounts, listIrcAccountIds, resolveDefaultIrcAccountId, resolveIrcAccount, setIrcRuntime };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as IrcChannelConfigSchema } from "./config-schema-
|
|
1
|
+
import { t as IrcChannelConfigSchema } from "./config-schema-DdB_h5mL.js";
|
|
2
2
|
import { t as getIrcRuntime } from "./runtime-xy-FcjJC.js";
|
|
3
3
|
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-D_DC3YWj.js";
|
|
4
4
|
import { createAccountListHelpers, describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
@@ -18,7 +18,7 @@ import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-i
|
|
|
18
18
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeStringifiedOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
19
19
|
import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, runPassiveAccountLifecycle, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
|
|
20
20
|
import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
|
|
21
|
-
import { chunkTextForOutbound, convertMarkdownTables, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
21
|
+
import { chunkTextForOutbound, convertMarkdownTables, sanitizeAssistantVisibleText, stripMarkdown } from "openclaw/plugin-sdk/text-chunking";
|
|
22
22
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
23
23
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
24
24
|
import net from "node:net";
|
|
@@ -183,7 +183,7 @@ const collectIrcMutableAllowlistWarnings = createDangerousNameMatchingMutableAll
|
|
|
183
183
|
});
|
|
184
184
|
//#endregion
|
|
185
185
|
//#region extensions/irc/src/gateway.ts
|
|
186
|
-
const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-
|
|
186
|
+
const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-kWMtRD4g.js"));
|
|
187
187
|
async function startIrcGatewayAccount(ctx) {
|
|
188
188
|
const account = ctx.account;
|
|
189
189
|
const statusSink = createAccountStatusSink({
|
|
@@ -334,7 +334,7 @@ function takeIrcPrivmsgChunk(text, maxChars, maxBytes) {
|
|
|
334
334
|
if (splitAt >= Math.floor(fitted.length / 2)) return fitted.slice(0, splitAt);
|
|
335
335
|
return fitted;
|
|
336
336
|
}
|
|
337
|
-
function
|
|
337
|
+
function toIrcError(err) {
|
|
338
338
|
if (err instanceof Error) return err;
|
|
339
339
|
return new Error(typeof err === "string" ? err : JSON.stringify(err));
|
|
340
340
|
}
|
|
@@ -391,7 +391,7 @@ async function connectIrcClient(options) {
|
|
|
391
391
|
rejectReady = reject;
|
|
392
392
|
});
|
|
393
393
|
const fail = (err) => {
|
|
394
|
-
const error =
|
|
394
|
+
const error = toIrcError(err);
|
|
395
395
|
if (options.onError) options.onError(error);
|
|
396
396
|
if (!ready && rejectReady) {
|
|
397
397
|
rejectReady(error);
|
|
@@ -726,9 +726,9 @@ async function sendMessageIrc(to, text, opts) {
|
|
|
726
726
|
channel: "irc",
|
|
727
727
|
accountId: account.accountId
|
|
728
728
|
});
|
|
729
|
-
const prepared = convertMarkdownTables(text.trim(), tableMode);
|
|
729
|
+
const prepared = stripMarkdown(convertMarkdownTables(text.trim(), tableMode));
|
|
730
|
+
if (!prepared.trim()) throw new Error("Message must be non-empty for IRC sends");
|
|
730
731
|
const payload = opts.replyTo ? `${prepared}\n\n[reply:${opts.replyTo}]` : prepared;
|
|
731
|
-
if (!payload.trim()) throw new Error("Message must be non-empty for IRC sends");
|
|
732
732
|
const client = opts.client;
|
|
733
733
|
if (client?.isReady()) client.sendPrivmsg(target, payload);
|
|
734
734
|
else {
|
|
@@ -1028,7 +1028,8 @@ const ircSetupContract = defineChannelSetupContract({
|
|
|
1028
1028
|
cli: {
|
|
1029
1029
|
flags: "--use-env",
|
|
1030
1030
|
description: "Use IRC environment configuration"
|
|
1031
|
-
}
|
|
1031
|
+
},
|
|
1032
|
+
envVars: ["IRC_HOST", "IRC_NICK"]
|
|
1032
1033
|
}
|
|
1033
1034
|
},
|
|
1034
1035
|
legacyAdapter: ircSetupAdapter
|
|
@@ -1398,7 +1399,7 @@ const meta = {
|
|
|
1398
1399
|
systemImage: "number",
|
|
1399
1400
|
markdownCapable: true
|
|
1400
1401
|
};
|
|
1401
|
-
const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-
|
|
1402
|
+
const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-kWMtRD4g.js"));
|
|
1402
1403
|
function normalizePairingTarget(raw) {
|
|
1403
1404
|
const normalized = normalizeIrcAllowEntry(raw);
|
|
1404
1405
|
if (!normalized) return "";
|
|
@@ -1470,7 +1471,6 @@ const ircPlugin = createChatChannelPlugin({
|
|
|
1470
1471
|
...meta,
|
|
1471
1472
|
quickstartAllowFrom: true
|
|
1472
1473
|
},
|
|
1473
|
-
setup: ircSetupAdapter,
|
|
1474
1474
|
setupContract: ircSetupContract,
|
|
1475
1475
|
setupWizard: ircSetupWizard,
|
|
1476
1476
|
capabilities: {
|
|
@@ -1532,6 +1532,10 @@ const ircPlugin = createChatChannelPlugin({
|
|
|
1532
1532
|
messaging: {
|
|
1533
1533
|
targetPrefixes: ["irc"],
|
|
1534
1534
|
normalizeTarget: normalizeIrcMessagingTarget,
|
|
1535
|
+
inferTargetChatType: ({ to }) => {
|
|
1536
|
+
const target = normalizeIrcMessagingTarget(to);
|
|
1537
|
+
return target ? isChannelTarget(target) ? "group" : "direct" : void 0;
|
|
1538
|
+
},
|
|
1535
1539
|
resolveOutboundSessionRoute: (params) => resolveIrcOutboundSessionRoute(params),
|
|
1536
1540
|
targetResolver: {
|
|
1537
1541
|
looksLikeId: looksLikeIrcTargetId,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as IrcChannelConfigSchema } from "./config-schema-
|
|
1
|
+
import { t as IrcChannelConfigSchema } from "./config-schema-DdB_h5mL.js";
|
|
2
2
|
export { IrcChannelConfigSchema };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as ircPlugin } from "./channel-
|
|
1
|
+
import { t as ircPlugin } from "./channel-Bfg9kJRw.js";
|
|
2
2
|
export { ircPlugin };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { a as resolveIrcGroupRequireMention, c as buildIrcAllowlistCandidates, d as buildIrcConnectOptions, f as connectIrcClient, i as resolveIrcGroupMatch, l as isChannelTarget, m as parseIrcPrefix, o as sanitizeIrcAssistantText, p as parseIrcLine, s as sendMessageIrc, u as normalizeIrcAllowEntry, v as resolveIrcAccount } from "./channel-
|
|
1
|
+
import { a as resolveIrcGroupRequireMention, c as buildIrcAllowlistCandidates, d as buildIrcConnectOptions, f as connectIrcClient, i as resolveIrcGroupMatch, l as isChannelTarget, m as parseIrcPrefix, o as sanitizeIrcAssistantText, p as parseIrcLine, s as sendMessageIrc, u as normalizeIrcAllowEntry, v as resolveIrcAccount } from "./channel-Bfg9kJRw.js";
|
|
2
2
|
import { t as getIrcRuntime } from "./runtime-xy-FcjJC.js";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
6
|
import { resolveLoggerBackedRuntime } from "openclaw/plugin-sdk/extension-shared";
|
|
7
|
-
import {
|
|
7
|
+
import { channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
|
|
8
|
+
import { logInboundDrop, resolveChannelInboundRouteEnvelope } from "openclaw/plugin-sdk/channel-inbound";
|
|
8
9
|
import { channelIngressRoutes, createChannelIngressResolver, defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
9
10
|
import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
|
10
11
|
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
@@ -46,6 +47,23 @@ const ircIngressIdentity = defineStableChannelIngressIdentity({
|
|
|
46
47
|
resolveEntryId: ({ entryIndex, fieldKey }) => `irc-entry-${entryIndex + 1}:${fieldKey === "irc-nick" ? "nick" : "id"}`
|
|
47
48
|
});
|
|
48
49
|
const escapeIrcRegexLiteral = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
50
|
+
const IRC_NICK_CHARACTER = String.raw`[A-Za-z0-9_\-\[\]\\\x60^{}|~]`;
|
|
51
|
+
const IRC_RFC1459_CASE_EQUIVALENTS = /* @__PURE__ */ new Map([
|
|
52
|
+
["[", "{"],
|
|
53
|
+
["{", "["],
|
|
54
|
+
["]", "}"],
|
|
55
|
+
["}", "]"],
|
|
56
|
+
["\\", "|"],
|
|
57
|
+
["|", "\\"],
|
|
58
|
+
["^", "~"],
|
|
59
|
+
["~", "^"]
|
|
60
|
+
]);
|
|
61
|
+
function buildIrcNickMentionPattern(value) {
|
|
62
|
+
return Array.from(value, (character) => {
|
|
63
|
+
const equivalent = IRC_RFC1459_CASE_EQUIVALENTS.get(character);
|
|
64
|
+
return equivalent ? `[${escapeIrcRegexLiteral(character)}${escapeIrcRegexLiteral(equivalent)}]` : escapeIrcRegexLiteral(character);
|
|
65
|
+
}).join("");
|
|
66
|
+
}
|
|
49
67
|
function isBareNick(value) {
|
|
50
68
|
return !value.includes("!") && !value.includes("@");
|
|
51
69
|
}
|
|
@@ -165,7 +183,7 @@ async function handleIrcInbound(params) {
|
|
|
165
183
|
const hasControlCommand = core.channel.text.hasControlCommand(rawBody, config);
|
|
166
184
|
const mentionRegexes = core.channel.mentions.buildMentionRegexes(config);
|
|
167
185
|
const mentionNick = connectedNick?.trim() || account.nick;
|
|
168
|
-
const explicitMentionRegex = mentionNick ? new RegExp(
|
|
186
|
+
const explicitMentionRegex = mentionNick ? new RegExp(`(?<!${IRC_NICK_CHARACTER})${buildIrcNickMentionPattern(mentionNick)}(?!${IRC_NICK_CHARACTER})[:,]?`, "i") : null;
|
|
169
187
|
const wasMentioned = core.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes) || (explicitMentionRegex ? explicitMentionRegex.test(rawBody) : false);
|
|
170
188
|
const requireMention = message.isGroup ? resolveIrcGroupRequireMention({
|
|
171
189
|
groups: account.config.groups,
|
|
@@ -173,6 +191,17 @@ async function handleIrcInbound(params) {
|
|
|
173
191
|
}) : false;
|
|
174
192
|
const routeGroupAllowFrom = normalizeStringEntries(groupMatch.groupConfig?.allowFrom?.length ? groupMatch.groupConfig.allowFrom : groupMatch.wildcardConfig?.allowFrom);
|
|
175
193
|
const accessGroupPolicy = groupPolicy === "open" && (hasEntries(account.config.groupAllowFrom) || hasEntries(routeGroupAllowFrom)) ? "allowlist" : groupPolicy;
|
|
194
|
+
const channelTarget = message.target.startsWith("#") || message.target.startsWith("&") ? message.target : `#${message.target}`;
|
|
195
|
+
const peerId = message.isGroup ? channelTarget : message.senderNick;
|
|
196
|
+
const { route, buildEnvelope } = resolveChannelInboundRouteEnvelope({
|
|
197
|
+
cfg: config,
|
|
198
|
+
channel: CHANNEL_ID,
|
|
199
|
+
accountId: account.accountId,
|
|
200
|
+
peer: {
|
|
201
|
+
kind: message.isGroup ? "group" : "direct",
|
|
202
|
+
id: peerId
|
|
203
|
+
}
|
|
204
|
+
});
|
|
176
205
|
const access = await createChannelIngressResolver({
|
|
177
206
|
channelId: CHANNEL_ID,
|
|
178
207
|
accountId: account.accountId,
|
|
@@ -185,6 +214,12 @@ async function handleIrcInbound(params) {
|
|
|
185
214
|
kind: message.isGroup ? "group" : "direct",
|
|
186
215
|
id: message.target
|
|
187
216
|
},
|
|
217
|
+
contextBinding: {
|
|
218
|
+
agentId: route.agentId,
|
|
219
|
+
sessionKey: route.sessionKey,
|
|
220
|
+
...message.messageId ? { messageId: message.messageId } : {},
|
|
221
|
+
inboundEventKind: "user_request"
|
|
222
|
+
},
|
|
188
223
|
route: routeDescriptorsForIrcGroup({
|
|
189
224
|
isGroup: message.isGroup,
|
|
190
225
|
groupPolicy,
|
|
@@ -262,17 +297,6 @@ async function handleIrcInbound(params) {
|
|
|
262
297
|
kind: "failed-retryable",
|
|
263
298
|
error: turnAdoptionLifecycle.abortSignal.reason
|
|
264
299
|
};
|
|
265
|
-
const channelTarget = message.target.startsWith("#") || message.target.startsWith("&") ? message.target : `#${message.target}`;
|
|
266
|
-
const peerId = message.isGroup ? channelTarget : message.senderNick;
|
|
267
|
-
const { route, buildEnvelope } = resolveChannelInboundRouteEnvelope({
|
|
268
|
-
cfg: config,
|
|
269
|
-
channel: CHANNEL_ID,
|
|
270
|
-
accountId: account.accountId,
|
|
271
|
-
peer: {
|
|
272
|
-
kind: message.isGroup ? "group" : "direct",
|
|
273
|
-
id: peerId
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
300
|
const fromLabel = message.isGroup ? message.target : senderDisplay;
|
|
277
301
|
const body = buildEnvelope({
|
|
278
302
|
channel: "IRC",
|
|
@@ -282,7 +306,8 @@ async function handleIrcInbound(params) {
|
|
|
282
306
|
});
|
|
283
307
|
const groupSystemPrompt = normalizeOptionalString(groupMatch.groupConfig?.systemPrompt);
|
|
284
308
|
const blockStreamingEnabled = resolveChannelStreamingBlockEnabled(account.config);
|
|
285
|
-
const ctxPayload =
|
|
309
|
+
const ctxPayload = core.channel.inbound.buildContext({
|
|
310
|
+
channelIngress: access,
|
|
286
311
|
channel: CHANNEL_ID,
|
|
287
312
|
accountId: route.accountId,
|
|
288
313
|
messageId: message.messageId,
|
|
@@ -592,6 +617,7 @@ async function monitorIrcProvider(opts) {
|
|
|
592
617
|
});
|
|
593
618
|
function scheduleReconnect() {
|
|
594
619
|
if (stopped || monitorAbort.signal.aborted || reconnectTimer) return;
|
|
620
|
+
opts.statusSink?.({ lifecycle: "recovering" });
|
|
595
621
|
reconnectTimer = setTimeout(() => {
|
|
596
622
|
reconnectTimer = null;
|
|
597
623
|
connect().catch((error) => {
|
|
@@ -648,6 +674,7 @@ async function monitorIrcProvider(opts) {
|
|
|
648
674
|
return;
|
|
649
675
|
}
|
|
650
676
|
ingress.start();
|
|
677
|
+
opts.statusSink?.(channelReadyPatch());
|
|
651
678
|
logger.info(`[${account.accountId}] connected to ${account.host}:${account.port}${account.tls ? " (tls)" : ""} as ${nextClient.nick}`);
|
|
652
679
|
}
|
|
653
680
|
try {
|
|
@@ -59,6 +59,7 @@ const IrcNickServSchema = z.object({
|
|
|
59
59
|
const IrcChannelConfigSchema = buildChannelConfigSchema(buildMultiAccountChannelSchema(z.object({
|
|
60
60
|
name: z.string().optional(),
|
|
61
61
|
enabled: z.boolean().optional(),
|
|
62
|
+
configWrites: z.boolean().optional(),
|
|
62
63
|
dangerouslyAllowNameMatching: z.boolean().optional(),
|
|
63
64
|
host: z.string().optional(),
|
|
64
65
|
port: z.number().int().min(1).max(65535).optional(),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineChannelAliasMigration } from "openclaw/plugin-sdk/runtime-doctor";
|
|
1
|
+
import { defineChannelAliasMigration } from "openclaw/plugin-sdk/runtime-doctor-migrations";
|
|
2
2
|
//#region extensions/irc/doctor-contract-api.ts
|
|
3
3
|
const streamingAliasMigration = defineChannelAliasMigration({
|
|
4
4
|
channelId: "irc",
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "irc",
|
|
3
|
+
"doctorContract": {
|
|
4
|
+
"configRepair": true
|
|
5
|
+
},
|
|
3
6
|
"activation": {
|
|
4
7
|
"onStartup": false
|
|
5
8
|
},
|
|
@@ -23,6 +26,9 @@
|
|
|
23
26
|
"enabled": {
|
|
24
27
|
"type": "boolean"
|
|
25
28
|
},
|
|
29
|
+
"configWrites": {
|
|
30
|
+
"type": "boolean"
|
|
31
|
+
},
|
|
26
32
|
"dangerouslyAllowNameMatching": {
|
|
27
33
|
"type": "boolean"
|
|
28
34
|
},
|
|
@@ -346,6 +352,9 @@
|
|
|
346
352
|
"enabled": {
|
|
347
353
|
"type": "boolean"
|
|
348
354
|
},
|
|
355
|
+
"configWrites": {
|
|
356
|
+
"type": "boolean"
|
|
357
|
+
},
|
|
349
358
|
"dangerouslyAllowNameMatching": {
|
|
350
359
|
"type": "boolean"
|
|
351
360
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/irc",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.8.1-beta.2",
|
|
4
4
|
"description": "OpenClaw IRC channel plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"openclaw": {
|
|
@@ -111,16 +111,20 @@
|
|
|
111
111
|
"cli": {
|
|
112
112
|
"flags": "--use-env",
|
|
113
113
|
"description": "Use IRC environment configuration"
|
|
114
|
-
}
|
|
114
|
+
},
|
|
115
|
+
"envVars": [
|
|
116
|
+
"IRC_HOST",
|
|
117
|
+
"IRC_NICK"
|
|
118
|
+
]
|
|
115
119
|
}
|
|
116
120
|
]
|
|
117
121
|
}
|
|
118
122
|
},
|
|
119
123
|
"compat": {
|
|
120
|
-
"pluginApi": ">=2026.
|
|
124
|
+
"pluginApi": ">=2026.8.1-beta.2"
|
|
121
125
|
},
|
|
122
126
|
"build": {
|
|
123
|
-
"openclawVersion": "2026.
|
|
127
|
+
"openclawVersion": "2026.8.1-beta.2",
|
|
124
128
|
"bundledDist": false
|
|
125
129
|
},
|
|
126
130
|
"release": {
|
|
@@ -145,7 +149,7 @@
|
|
|
145
149
|
"README.md"
|
|
146
150
|
],
|
|
147
151
|
"peerDependencies": {
|
|
148
|
-
"openclaw": ">=2026.
|
|
152
|
+
"openclaw": ">=2026.8.1-beta.2"
|
|
149
153
|
},
|
|
150
154
|
"peerDependenciesMeta": {
|
|
151
155
|
"openclaw": {
|