@openclaw/irc 2026.7.2-beta.5 → 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-BZclM5wY.js → channel-Bfg9kJRw.js} +21 -23
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-runtime-CRzAwKGK.js → channel-runtime-kWMtRD4g.js} +50 -31
- 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
|
|
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";
|
|
@@ -12,12 +12,13 @@ import { buildBaseChannelStatusSummary, createComputedAccountStatusAdapter, crea
|
|
|
12
12
|
import { resolveAccountWithDefaultFallback } from "openclaw/plugin-sdk/account-core";
|
|
13
13
|
import { DEFAULT_ACCOUNT_ID, DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
14
14
|
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
15
|
+
import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
|
|
15
16
|
import { tryReadSecretFileSync } from "openclaw/plugin-sdk/secret-file-runtime";
|
|
16
17
|
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
17
18
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeStringifiedOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
19
|
import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, runPassiveAccountLifecycle, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
|
|
19
20
|
import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
|
|
20
|
-
import { chunkTextForOutbound, convertMarkdownTables, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
21
|
+
import { chunkTextForOutbound, convertMarkdownTables, sanitizeAssistantVisibleText, stripMarkdown } from "openclaw/plugin-sdk/text-chunking";
|
|
21
22
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
22
23
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
23
24
|
import net from "node:net";
|
|
@@ -28,16 +29,6 @@ import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
|
|
|
28
29
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1 } from "openclaw/plugin-sdk/routing";
|
|
29
30
|
import { applyAccountNameToChannelSection, createAllowFromSection, createPromptParsedAllowFromForAccount, createSetupInputPresenceValidator, createSetupTranslator, createStandardChannelSetupStatus, createTopLevelChannelAllowFromSetter, createTopLevelChannelDmPolicySetter, formatDocsLink, patchScopedAccountConfig, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
|
30
31
|
//#region extensions/irc/src/accounts.ts
|
|
31
|
-
const TRUTHY_ENV = /* @__PURE__ */ new Set([
|
|
32
|
-
"true",
|
|
33
|
-
"1",
|
|
34
|
-
"yes",
|
|
35
|
-
"on"
|
|
36
|
-
]);
|
|
37
|
-
function parseTruthy(value) {
|
|
38
|
-
if (!value) return false;
|
|
39
|
-
return TRUTHY_ENV.has(normalizeLowercaseStringOrEmpty(value));
|
|
40
|
-
}
|
|
41
32
|
function parseIntEnv(value) {
|
|
42
33
|
if (!value?.trim()) return;
|
|
43
34
|
const parsed = parseStrictPositiveInteger(value);
|
|
@@ -128,7 +119,7 @@ function resolveIrcAccount(params) {
|
|
|
128
119
|
const merged = mergeIrcAccountConfig(params.cfg, accountId);
|
|
129
120
|
const accountEnabled = merged.enabled !== false;
|
|
130
121
|
const enabled = baseEnabled && accountEnabled;
|
|
131
|
-
const tls = typeof merged.tls === "boolean" ? merged.tls : accountId === DEFAULT_ACCOUNT_ID && process.env.IRC_TLS ?
|
|
122
|
+
const tls = typeof merged.tls === "boolean" ? merged.tls : accountId === DEFAULT_ACCOUNT_ID && process.env.IRC_TLS ? isTruthyEnvValue(process.env.IRC_TLS) : true;
|
|
132
123
|
const envPort = accountId === DEFAULT_ACCOUNT_ID ? parseIntEnv(process.env.IRC_PORT) : void 0;
|
|
133
124
|
const port = merged.port ?? envPort ?? (tls ? 6697 : 6667);
|
|
134
125
|
const envChannels = accountId === DEFAULT_ACCOUNT_ID ? parseOptionalDelimitedEntries(process.env.IRC_CHANNELS) : void 0;
|
|
@@ -192,7 +183,7 @@ const collectIrcMutableAllowlistWarnings = createDangerousNameMatchingMutableAll
|
|
|
192
183
|
});
|
|
193
184
|
//#endregion
|
|
194
185
|
//#region extensions/irc/src/gateway.ts
|
|
195
|
-
const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-
|
|
186
|
+
const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-kWMtRD4g.js"));
|
|
196
187
|
async function startIrcGatewayAccount(ctx) {
|
|
197
188
|
const account = ctx.account;
|
|
198
189
|
const statusSink = createAccountStatusSink({
|
|
@@ -343,7 +334,7 @@ function takeIrcPrivmsgChunk(text, maxChars, maxBytes) {
|
|
|
343
334
|
if (splitAt >= Math.floor(fitted.length / 2)) return fitted.slice(0, splitAt);
|
|
344
335
|
return fitted;
|
|
345
336
|
}
|
|
346
|
-
function
|
|
337
|
+
function toIrcError(err) {
|
|
347
338
|
if (err instanceof Error) return err;
|
|
348
339
|
return new Error(typeof err === "string" ? err : JSON.stringify(err));
|
|
349
340
|
}
|
|
@@ -400,7 +391,7 @@ async function connectIrcClient(options) {
|
|
|
400
391
|
rejectReady = reject;
|
|
401
392
|
});
|
|
402
393
|
const fail = (err) => {
|
|
403
|
-
const error =
|
|
394
|
+
const error = toIrcError(err);
|
|
404
395
|
if (options.onError) options.onError(error);
|
|
405
396
|
if (!ready && rejectReady) {
|
|
406
397
|
rejectReady(error);
|
|
@@ -735,9 +726,9 @@ async function sendMessageIrc(to, text, opts) {
|
|
|
735
726
|
channel: "irc",
|
|
736
727
|
accountId: account.accountId
|
|
737
728
|
});
|
|
738
|
-
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");
|
|
739
731
|
const payload = opts.replyTo ? `${prepared}\n\n[reply:${opts.replyTo}]` : prepared;
|
|
740
|
-
if (!payload.trim()) throw new Error("Message must be non-empty for IRC sends");
|
|
741
732
|
const client = opts.client;
|
|
742
733
|
if (client?.isReady()) client.sendPrivmsg(target, payload);
|
|
743
734
|
else {
|
|
@@ -786,12 +777,15 @@ const ircMessageAdapter = defineChannelMessageAdapter({
|
|
|
786
777
|
});
|
|
787
778
|
//#endregion
|
|
788
779
|
//#region extensions/irc/src/outbound-base.ts
|
|
780
|
+
function sanitizeIrcAssistantText(text) {
|
|
781
|
+
return sanitizeForPlainText(sanitizeAssistantVisibleText(text));
|
|
782
|
+
}
|
|
789
783
|
const ircOutboundBaseAdapter = {
|
|
790
784
|
deliveryMode: "direct",
|
|
791
785
|
chunker: chunkTextForOutbound,
|
|
792
786
|
chunkerMode: "markdown",
|
|
793
787
|
textChunkLimit: 350,
|
|
794
|
-
sanitizeText: ({ text }) =>
|
|
788
|
+
sanitizeText: ({ text }) => sanitizeIrcAssistantText(text)
|
|
795
789
|
};
|
|
796
790
|
//#endregion
|
|
797
791
|
//#region extensions/irc/src/policy.ts
|
|
@@ -1034,7 +1028,8 @@ const ircSetupContract = defineChannelSetupContract({
|
|
|
1034
1028
|
cli: {
|
|
1035
1029
|
flags: "--use-env",
|
|
1036
1030
|
description: "Use IRC environment configuration"
|
|
1037
|
-
}
|
|
1031
|
+
},
|
|
1032
|
+
envVars: ["IRC_HOST", "IRC_NICK"]
|
|
1038
1033
|
}
|
|
1039
1034
|
},
|
|
1040
1035
|
legacyAdapter: ircSetupAdapter
|
|
@@ -1404,7 +1399,7 @@ const meta = {
|
|
|
1404
1399
|
systemImage: "number",
|
|
1405
1400
|
markdownCapable: true
|
|
1406
1401
|
};
|
|
1407
|
-
const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-
|
|
1402
|
+
const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-kWMtRD4g.js"));
|
|
1408
1403
|
function normalizePairingTarget(raw) {
|
|
1409
1404
|
const normalized = normalizeIrcAllowEntry(raw);
|
|
1410
1405
|
if (!normalized) return "";
|
|
@@ -1476,7 +1471,6 @@ const ircPlugin = createChatChannelPlugin({
|
|
|
1476
1471
|
...meta,
|
|
1477
1472
|
quickstartAllowFrom: true
|
|
1478
1473
|
},
|
|
1479
|
-
setup: ircSetupAdapter,
|
|
1480
1474
|
setupContract: ircSetupContract,
|
|
1481
1475
|
setupWizard: ircSetupWizard,
|
|
1482
1476
|
capabilities: {
|
|
@@ -1538,6 +1532,10 @@ const ircPlugin = createChatChannelPlugin({
|
|
|
1538
1532
|
messaging: {
|
|
1539
1533
|
targetPrefixes: ["irc"],
|
|
1540
1534
|
normalizeTarget: normalizeIrcMessagingTarget,
|
|
1535
|
+
inferTargetChatType: ({ to }) => {
|
|
1536
|
+
const target = normalizeIrcMessagingTarget(to);
|
|
1537
|
+
return target ? isChannelTarget(target) ? "group" : "direct" : void 0;
|
|
1538
|
+
},
|
|
1541
1539
|
resolveOutboundSessionRoute: (params) => resolveIrcOutboundSessionRoute(params),
|
|
1542
1540
|
targetResolver: {
|
|
1543
1541
|
looksLikeId: looksLikeIrcTargetId,
|
|
@@ -1644,4 +1642,4 @@ const ircPlugin = createChatChannelPlugin({
|
|
|
1644
1642
|
}
|
|
1645
1643
|
});
|
|
1646
1644
|
//#endregion
|
|
1647
|
-
export {
|
|
1645
|
+
export { resolveDefaultIrcAccountId as _, resolveIrcGroupRequireMention as a, buildIrcAllowlistCandidates as c, buildIrcConnectOptions as d, connectIrcClient as f, listIrcAccountIds as g, listEnabledIrcAccounts as h, resolveIrcGroupMatch as i, isChannelTarget as l, parseIrcPrefix as m, ircSetupWizard as n, sanitizeIrcAssistantText as o, parseIrcLine as p, ircSetupAdapter as r, sendMessageIrc as s, ircPlugin as t, normalizeIrcAllowEntry as u, resolveIrcAccount as v };
|
|
@@ -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 {
|
|
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
|
-
import { bindIngressLifecycleToReplyOptions, createChannelIngressMonitor, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
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
|
}
|
|
@@ -108,7 +126,10 @@ function routeDescriptorsForIrcGroup(params) {
|
|
|
108
126
|
}
|
|
109
127
|
async function deliverIrcReply(params) {
|
|
110
128
|
await deliverFormattedTextWithAttachments({
|
|
111
|
-
payload:
|
|
129
|
+
payload: {
|
|
130
|
+
...params.payload,
|
|
131
|
+
text: sanitizeIrcAssistantText(params.payload.text ?? "")
|
|
132
|
+
},
|
|
112
133
|
send: async ({ text, replyToId }) => {
|
|
113
134
|
if (params.sendReply) await params.sendReply(params.target, text, replyToId);
|
|
114
135
|
else await sendMessageIrc(params.target, text, {
|
|
@@ -162,7 +183,7 @@ async function handleIrcInbound(params) {
|
|
|
162
183
|
const hasControlCommand = core.channel.text.hasControlCommand(rawBody, config);
|
|
163
184
|
const mentionRegexes = core.channel.mentions.buildMentionRegexes(config);
|
|
164
185
|
const mentionNick = connectedNick?.trim() || account.nick;
|
|
165
|
-
const explicitMentionRegex = mentionNick ? new RegExp(
|
|
186
|
+
const explicitMentionRegex = mentionNick ? new RegExp(`(?<!${IRC_NICK_CHARACTER})${buildIrcNickMentionPattern(mentionNick)}(?!${IRC_NICK_CHARACTER})[:,]?`, "i") : null;
|
|
166
187
|
const wasMentioned = core.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes) || (explicitMentionRegex ? explicitMentionRegex.test(rawBody) : false);
|
|
167
188
|
const requireMention = message.isGroup ? resolveIrcGroupRequireMention({
|
|
168
189
|
groups: account.config.groups,
|
|
@@ -170,6 +191,17 @@ async function handleIrcInbound(params) {
|
|
|
170
191
|
}) : false;
|
|
171
192
|
const routeGroupAllowFrom = normalizeStringEntries(groupMatch.groupConfig?.allowFrom?.length ? groupMatch.groupConfig.allowFrom : groupMatch.wildcardConfig?.allowFrom);
|
|
172
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
|
+
});
|
|
173
205
|
const access = await createChannelIngressResolver({
|
|
174
206
|
channelId: CHANNEL_ID,
|
|
175
207
|
accountId: account.accountId,
|
|
@@ -182,6 +214,12 @@ async function handleIrcInbound(params) {
|
|
|
182
214
|
kind: message.isGroup ? "group" : "direct",
|
|
183
215
|
id: message.target
|
|
184
216
|
},
|
|
217
|
+
contextBinding: {
|
|
218
|
+
agentId: route.agentId,
|
|
219
|
+
sessionKey: route.sessionKey,
|
|
220
|
+
...message.messageId ? { messageId: message.messageId } : {},
|
|
221
|
+
inboundEventKind: "user_request"
|
|
222
|
+
},
|
|
185
223
|
route: routeDescriptorsForIrcGroup({
|
|
186
224
|
isGroup: message.isGroup,
|
|
187
225
|
groupPolicy,
|
|
@@ -259,17 +297,6 @@ async function handleIrcInbound(params) {
|
|
|
259
297
|
kind: "failed-retryable",
|
|
260
298
|
error: turnAdoptionLifecycle.abortSignal.reason
|
|
261
299
|
};
|
|
262
|
-
const channelTarget = message.target.startsWith("#") || message.target.startsWith("&") ? message.target : `#${message.target}`;
|
|
263
|
-
const peerId = message.isGroup ? channelTarget : message.senderNick;
|
|
264
|
-
const { route, buildEnvelope } = resolveChannelInboundRouteEnvelope({
|
|
265
|
-
cfg: config,
|
|
266
|
-
channel: CHANNEL_ID,
|
|
267
|
-
accountId: account.accountId,
|
|
268
|
-
peer: {
|
|
269
|
-
kind: message.isGroup ? "group" : "direct",
|
|
270
|
-
id: peerId
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
300
|
const fromLabel = message.isGroup ? message.target : senderDisplay;
|
|
274
301
|
const body = buildEnvelope({
|
|
275
302
|
channel: "IRC",
|
|
@@ -279,7 +306,8 @@ async function handleIrcInbound(params) {
|
|
|
279
306
|
});
|
|
280
307
|
const groupSystemPrompt = normalizeOptionalString(groupMatch.groupConfig?.systemPrompt);
|
|
281
308
|
const blockStreamingEnabled = resolveChannelStreamingBlockEnabled(account.config);
|
|
282
|
-
const ctxPayload =
|
|
309
|
+
const ctxPayload = core.channel.inbound.buildContext({
|
|
310
|
+
channelIngress: access,
|
|
283
311
|
channel: CHANNEL_ID,
|
|
284
312
|
accountId: route.accountId,
|
|
285
313
|
messageId: message.messageId,
|
|
@@ -386,15 +414,7 @@ async function handleIrcInbound(params) {
|
|
|
386
414
|
//#region extensions/irc/src/irc-ingress.ts
|
|
387
415
|
const IRC_INGRESS_PAYLOAD_VERSION = 1;
|
|
388
416
|
const IRC_INGRESS_POLL_INTERVAL_MS = 1e3;
|
|
389
|
-
const
|
|
390
|
-
const IRC_INGRESS_TOMBSTONE_TTL_MS = 720 * 60 * 60 * 1e3;
|
|
391
|
-
const IRC_INGRESS_TOMBSTONE_MAX_ENTRIES = 1e3;
|
|
392
|
-
var IrcIngressPayloadError = class extends Error {
|
|
393
|
-
constructor(message) {
|
|
394
|
-
super(message);
|
|
395
|
-
this.name = "IrcIngressPayloadError";
|
|
396
|
-
}
|
|
397
|
-
};
|
|
417
|
+
const IrcIngressPayloadError = createChannelIngressError("IrcIngressPayloadError");
|
|
398
418
|
function inspectRawPrivmsg(rawLine) {
|
|
399
419
|
const line = parseIrcLine(rawLine);
|
|
400
420
|
if (!line || line.command !== "PRIVMSG") throw new IrcIngressPayloadError("IRC ingress row is not a PRIVMSG line.");
|
|
@@ -481,11 +501,8 @@ function createIrcIngressMonitor(options) {
|
|
|
481
501
|
},
|
|
482
502
|
pollIntervalMs: options.pollIntervalMs ?? IRC_INGRESS_POLL_INTERVAL_MS,
|
|
483
503
|
retention: {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
completedMaxEntries: IRC_INGRESS_TOMBSTONE_MAX_ENTRIES,
|
|
487
|
-
failedTtlMs: IRC_INGRESS_TOMBSTONE_TTL_MS,
|
|
488
|
-
failedMaxEntries: IRC_INGRESS_TOMBSTONE_MAX_ENTRIES
|
|
504
|
+
completedMaxEntries: 1e3,
|
|
505
|
+
failedMaxEntries: 1e3
|
|
489
506
|
},
|
|
490
507
|
drain: {
|
|
491
508
|
resolveNonRetryableFailure: resolveIrcIngressNonRetryableFailure,
|
|
@@ -600,6 +617,7 @@ async function monitorIrcProvider(opts) {
|
|
|
600
617
|
});
|
|
601
618
|
function scheduleReconnect() {
|
|
602
619
|
if (stopped || monitorAbort.signal.aborted || reconnectTimer) return;
|
|
620
|
+
opts.statusSink?.({ lifecycle: "recovering" });
|
|
603
621
|
reconnectTimer = setTimeout(() => {
|
|
604
622
|
reconnectTimer = null;
|
|
605
623
|
connect().catch((error) => {
|
|
@@ -656,6 +674,7 @@ async function monitorIrcProvider(opts) {
|
|
|
656
674
|
return;
|
|
657
675
|
}
|
|
658
676
|
ingress.start();
|
|
677
|
+
opts.statusSink?.(channelReadyPatch());
|
|
659
678
|
logger.info(`[${account.accountId}] connected to ${account.host}:${account.port}${account.tls ? " (tls)" : ""} as ${nextClient.nick}`);
|
|
660
679
|
}
|
|
661
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": {
|