@openclaw/irc 2026.8.1-beta.3 → 2026.9.1-beta.1

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 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-BO1GdA4V.js";
1
+ import { _ as resolveDefaultIrcAccountId, g as listIrcAccountIds, h as listEnabledIrcAccounts, n as ircSetupWizard, r as ircSetupAdapter, t as ircPlugin, v as resolveIrcAccount } from "./channel-W4DLS5ip.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-DdB_h5mL.js";
1
+ import { t as IrcChannelConfigSchema } from "./config-schema-BDXGjxOr.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";
@@ -16,9 +16,10 @@ import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
16
16
  import { tryReadSecretFileSync } from "openclaw/plugin-sdk/secret-file-runtime";
17
17
  import { resolveSecretInputString } from "openclaw/plugin-sdk/secret-input";
18
18
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeStringifiedOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
19
- import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, runPassiveAccountLifecycle, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
19
+ import { createAccountStatusSink, createMessageReceiptFromOutboundResults, createReplyToFanout, defineChannelMessageAdapter, runPassiveAccountLifecycle, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
20
20
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
21
21
  import { chunkTextForOutbound, convertMarkdownTables, sanitizeAssistantVisibleText, stripMarkdown } from "openclaw/plugin-sdk/text-chunking";
22
+ import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result";
22
23
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
23
24
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
24
25
  import net from "node:net";
@@ -197,7 +198,7 @@ const collectIrcMutableAllowlistWarnings = createDangerousNameMatchingMutableAll
197
198
  });
198
199
  //#endregion
199
200
  //#region extensions/irc/src/gateway.ts
200
- const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-CSpBc1ef.js"));
201
+ const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-CA62Mbrh.js"));
201
202
  async function startIrcGatewayAccount(ctx) {
202
203
  const account = ctx.account;
203
204
  const statusSink = createAccountStatusSink({
@@ -222,6 +223,18 @@ async function startIrcGatewayAccount(ctx) {
222
223
  });
223
224
  }
224
225
  //#endregion
226
+ //#region extensions/irc/src/outbound-base.ts
227
+ function sanitizeIrcAssistantText(text) {
228
+ return sanitizeForPlainText(sanitizeAssistantVisibleText(text));
229
+ }
230
+ const ircOutboundBaseAdapter = {
231
+ deliveryMode: "direct",
232
+ chunker: chunkTextForOutbound,
233
+ chunkerMode: "markdown",
234
+ textChunkLimit: 350,
235
+ sanitizeText: ({ text }) => sanitizeIrcAssistantText(text)
236
+ };
237
+ //#endregion
225
238
  //#region extensions/irc/src/control-chars.ts
226
239
  function isIrcControlChar(charCode) {
227
240
  return charCode <= 31 || charCode === 127;
@@ -729,7 +742,7 @@ function resolveTarget(to, opts) {
729
742
  if (fromOpt) return fromOpt;
730
743
  throw new Error(`Invalid IRC target: ${to}`);
731
744
  }
732
- async function sendMessageIrc(to, text, opts) {
745
+ async function sendIrcMessages(to, messages, opts, onDeliveryResult) {
733
746
  const cfg = requireRuntimeConfig(opts.cfg, "IRC send");
734
747
  const account = resolveIrcAccount({
735
748
  cfg,
@@ -742,37 +755,66 @@ async function sendMessageIrc(to, text, opts) {
742
755
  channel: "irc",
743
756
  accountId: account.accountId
744
757
  });
745
- const prepared = stripMarkdown(convertMarkdownTables(text.trim(), tableMode));
746
- if (!prepared.trim()) throw new Error("Message must be non-empty for IRC sends");
747
- const payload = opts.replyTo ? `${prepared}\n\n[reply:${opts.replyTo}]` : prepared;
748
- const client = opts.client;
749
- if (client?.isReady()) client.sendPrivmsg(target, payload);
750
- else {
751
- const transient = await connectIrcClient(buildIrcConnectOptions(account, { connectTimeoutMs: 12e3 }));
752
- if (target.startsWith("#") || target.startsWith("&")) transient.join(target);
753
- transient.sendPrivmsg(target, payload);
754
- transient.quit("sent");
755
- }
756
- recordIrcOutboundActivity(account.accountId);
757
- const messageId = makeIrcMessageId();
758
- return {
759
- messageId,
760
- target,
761
- receipt: createMessageReceiptFromOutboundResults({
762
- results: [{
763
- channel: "irc",
758
+ const preparedMessages = messages.map((message) => {
759
+ const prepared = stripMarkdown(convertMarkdownTables(message.text.trim(), tableMode));
760
+ if (!prepared.trim()) throw new Error("Message must be non-empty for IRC sends");
761
+ return {
762
+ payload: message.replyTo ? `${prepared}\n\n[reply:${message.replyTo}]` : prepared,
763
+ replyTo: message.replyTo
764
+ };
765
+ });
766
+ if (preparedMessages.length === 0) return [];
767
+ opts.abortSignal?.throwIfAborted();
768
+ let transient;
769
+ const client = opts.client?.isReady() ? opts.client : transient = await connectIrcClient(buildIrcConnectOptions(account, {
770
+ connectTimeoutMs: 12e3,
771
+ abortSignal: opts.abortSignal
772
+ }));
773
+ const results = [];
774
+ try {
775
+ opts.abortSignal?.throwIfAborted();
776
+ if (transient && (target.startsWith("#") || target.startsWith("&"))) client.join(target);
777
+ for (const message of preparedMessages) {
778
+ opts.abortSignal?.throwIfAborted();
779
+ if (!client.isReady()) throw new Error("IRC connection closed before send");
780
+ await opts.onPlatformSendDispatch?.();
781
+ opts.abortSignal?.throwIfAborted();
782
+ if (!client.isReady()) throw new Error("IRC connection closed before send");
783
+ client.sendPrivmsg(target, message.payload);
784
+ recordIrcOutboundActivity(account.accountId);
785
+ const messageId = makeIrcMessageId();
786
+ const result = {
764
787
  messageId,
765
- conversationId: target
766
- }],
767
- kind: "text",
768
- ...opts.replyTo ? { replyToId: opts.replyTo } : {}
769
- })
770
- };
788
+ target,
789
+ receipt: createMessageReceiptFromOutboundResults({
790
+ results: [{
791
+ channel: "irc",
792
+ messageId,
793
+ conversationId: target
794
+ }],
795
+ kind: "text",
796
+ ...message.replyTo ? { replyToId: message.replyTo } : {}
797
+ })
798
+ };
799
+ results.push(result);
800
+ await onDeliveryResult?.(result);
801
+ }
802
+ return results;
803
+ } finally {
804
+ transient?.quit("sent");
805
+ }
806
+ }
807
+ async function sendMessageIrc(to, text, opts) {
808
+ const result = (await sendIrcMessages(to, [{
809
+ text,
810
+ ...opts.replyTo ? { replyTo: opts.replyTo } : {}
811
+ }], opts))[0];
812
+ if (!result) throw new Error("Message must be non-empty for IRC sends");
813
+ return result;
771
814
  }
772
815
  //#endregion
773
816
  //#region extensions/irc/src/message-adapter.ts
774
- async function sendIrcMessage(...args) {
775
- const { target, ...result } = await sendMessageIrc(...args);
817
+ function toIrcMessageResult({ target, ...result }) {
776
818
  return {
777
819
  ...result,
778
820
  target: {
@@ -781,6 +823,40 @@ async function sendIrcMessage(...args) {
781
823
  }
782
824
  };
783
825
  }
826
+ async function sendIrcMessage(...args) {
827
+ return toIrcMessageResult(await sendMessageIrc(...args));
828
+ }
829
+ const sendFormattedIrcText = async (ctx) => {
830
+ const { chunkMarkdownTextWithMode, resolveChunkMode, resolveTextChunkLimit } = await import("openclaw/plugin-sdk/reply-chunking");
831
+ const accountId = ctx.accountId ?? void 0;
832
+ const textLimit = ctx.formatting?.textLimit ?? resolveTextChunkLimit(ctx.cfg, "irc", accountId, { fallbackLimit: ircOutboundBaseAdapter.textChunkLimit });
833
+ const chunkMode = ctx.formatting?.chunkMode ?? resolveChunkMode(ctx.cfg, "irc", accountId);
834
+ const chunkText = (text) => ctx.formatting ? ircOutboundBaseAdapter.chunker(text, textLimit, { formatting: ctx.formatting }) : ircOutboundBaseAdapter.chunker(text, textLimit);
835
+ let chunks;
836
+ if (chunkMode === "newline") {
837
+ const blocks = chunkMarkdownTextWithMode(ctx.text, textLimit, chunkMode);
838
+ if (blocks.length === 0 && ctx.text) blocks.push(ctx.text);
839
+ chunks = blocks.flatMap((block) => {
840
+ const blockChunks = chunkText(block);
841
+ return blockChunks.length === 0 && block ? [block] : blockChunks;
842
+ });
843
+ } else chunks = chunkText(ctx.text);
844
+ const nextReplyToId = createReplyToFanout(ctx);
845
+ return (await sendIrcMessages(ctx.to, chunks.map((text) => {
846
+ const replyTo = nextReplyToId();
847
+ return replyTo ? {
848
+ text,
849
+ replyTo
850
+ } : { text };
851
+ }), {
852
+ cfg: ctx.cfg,
853
+ accountId,
854
+ abortSignal: ctx.abortSignal,
855
+ onPlatformSendDispatch: ctx.onPlatformSendDispatch
856
+ }, async (result) => {
857
+ await ctx.onDeliveryResult?.(attachChannelToResult("irc", toIrcMessageResult(result)));
858
+ })).map((result) => attachChannelToResult("irc", toIrcMessageResult(result)));
859
+ };
784
860
  const ircMessageAdapter = defineChannelMessageAdapter({
785
861
  id: "irc",
786
862
  durableFinal: { capabilities: {
@@ -802,18 +878,6 @@ const ircMessageAdapter = defineChannelMessageAdapter({
802
878
  }
803
879
  });
804
880
  //#endregion
805
- //#region extensions/irc/src/outbound-base.ts
806
- function sanitizeIrcAssistantText(text) {
807
- return sanitizeForPlainText(sanitizeAssistantVisibleText(text));
808
- }
809
- const ircOutboundBaseAdapter = {
810
- deliveryMode: "direct",
811
- chunker: chunkTextForOutbound,
812
- chunkerMode: "markdown",
813
- textChunkLimit: 350,
814
- sanitizeText: ({ text }) => sanitizeIrcAssistantText(text)
815
- };
816
- //#endregion
817
881
  //#region extensions/irc/src/policy.ts
818
882
  function resolveIrcGroupScope(params) {
819
883
  const { "*": wildcard, ...groups } = params.groups ?? {};
@@ -1425,7 +1489,7 @@ const meta = {
1425
1489
  systemImage: "number",
1426
1490
  markdownCapable: true
1427
1491
  };
1428
- const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-CSpBc1ef.js"));
1492
+ const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-CA62Mbrh.js"));
1429
1493
  function normalizePairingTarget(raw) {
1430
1494
  const normalized = normalizeIrcAllowEntry(raw);
1431
1495
  if (!normalized) return "";
@@ -1668,7 +1732,10 @@ const ircPlugin = createChatChannelPlugin({
1668
1732
  collectWarnings: collectIrcSecurityWarnings
1669
1733
  },
1670
1734
  outbound: {
1671
- base: ircOutboundBaseAdapter,
1735
+ base: {
1736
+ ...ircOutboundBaseAdapter,
1737
+ sendFormattedText: sendFormattedIrcText
1738
+ },
1672
1739
  attachedResults: {
1673
1740
  channel: "irc",
1674
1741
  sendText: ({ onDeliveryResult: _onDeliveryResult, ...ctx }) => ircMessageAdapter.send.text(ctx),
@@ -1680,4 +1747,4 @@ const ircPlugin = createChatChannelPlugin({
1680
1747
  }
1681
1748
  });
1682
1749
  //#endregion
1683
- 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 };
1750
+ export { resolveDefaultIrcAccountId as _, resolveIrcGroupRequireMention as a, isChannelTarget as c, connectIrcClient as d, parseIrcLine as f, listIrcAccountIds as g, listEnabledIrcAccounts as h, resolveIrcGroupMatch as i, normalizeIrcAllowEntry as l, sanitizeIrcAssistantText as m, ircSetupWizard as n, sendMessageIrc as o, parseIrcPrefix as p, ircSetupAdapter as r, buildIrcAllowlistCandidates as s, ircPlugin as t, buildIrcConnectOptions as u, resolveIrcAccount as v };
@@ -1,2 +1,2 @@
1
- import { t as IrcChannelConfigSchema } from "./config-schema-DdB_h5mL.js";
1
+ import { t as IrcChannelConfigSchema } from "./config-schema-BDXGjxOr.js";
2
2
  export { IrcChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as ircPlugin } from "./channel-BO1GdA4V.js";
1
+ import { t as ircPlugin } from "./channel-W4DLS5ip.js";
2
2
  export { ircPlugin };
@@ -1,4 +1,4 @@
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-BO1GdA4V.js";
1
+ import { a as resolveIrcGroupRequireMention, c as isChannelTarget, d as connectIrcClient, f as parseIrcLine, i as resolveIrcGroupMatch, l as normalizeIrcAllowEntry, m as sanitizeIrcAssistantText, o as sendMessageIrc, p as parseIrcPrefix, s as buildIrcAllowlistCandidates, u as buildIrcConnectOptions, v as resolveIrcAccount } from "./channel-W4DLS5ip.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";
@@ -1,5 +1,5 @@
1
1
  import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
2
- import { ChannelGroupEntrySchema, DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, ReplyRuntimeConfigSchemaShape, buildChannelConfigSchema, buildMultiAccountChannelSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
2
+ import { ChannelGroupEntrySchema, DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, ReplyRuntimeConfigSchemaShape, ReplyToModeSchema, buildChannelConfigSchema, buildMultiAccountChannelSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
3
3
  import { z } from "zod";
4
4
  //#region extensions/irc/src/config-ui-hints.ts
5
5
  const ircChannelConfigUiHints = {
@@ -60,6 +60,7 @@ const IrcChannelConfigSchema = buildChannelConfigSchema(buildMultiAccountChannel
60
60
  name: z.string().optional(),
61
61
  enabled: z.boolean().optional(),
62
62
  configWrites: z.boolean().optional(),
63
+ replyToMode: ReplyToModeSchema.optional(),
63
64
  dangerouslyAllowNameMatching: z.boolean().optional(),
64
65
  host: z.string().optional(),
65
66
  port: z.number().int().min(1).max(65535).optional(),
@@ -29,6 +29,26 @@
29
29
  "configWrites": {
30
30
  "type": "boolean"
31
31
  },
32
+ "replyToMode": {
33
+ "anyOf": [
34
+ {
35
+ "type": "string",
36
+ "const": "off"
37
+ },
38
+ {
39
+ "type": "string",
40
+ "const": "first"
41
+ },
42
+ {
43
+ "type": "string",
44
+ "const": "all"
45
+ },
46
+ {
47
+ "type": "string",
48
+ "const": "batched"
49
+ }
50
+ ]
51
+ },
32
52
  "dangerouslyAllowNameMatching": {
33
53
  "type": "boolean"
34
54
  },
@@ -355,6 +375,26 @@
355
375
  "configWrites": {
356
376
  "type": "boolean"
357
377
  },
378
+ "replyToMode": {
379
+ "anyOf": [
380
+ {
381
+ "type": "string",
382
+ "const": "off"
383
+ },
384
+ {
385
+ "type": "string",
386
+ "const": "first"
387
+ },
388
+ {
389
+ "type": "string",
390
+ "const": "all"
391
+ },
392
+ {
393
+ "type": "string",
394
+ "const": "batched"
395
+ }
396
+ ]
397
+ },
358
398
  "dangerouslyAllowNameMatching": {
359
399
  "type": "boolean"
360
400
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/irc",
3
- "version": "2026.8.1-beta.3",
3
+ "version": "2026.9.1-beta.1",
4
4
  "description": "OpenClaw IRC channel plugin",
5
5
  "type": "module",
6
6
  "openclaw": {
@@ -121,10 +121,10 @@
121
121
  }
122
122
  },
123
123
  "compat": {
124
- "pluginApi": ">=2026.8.1-beta.3"
124
+ "pluginApi": ">=2026.9.1-beta.1"
125
125
  },
126
126
  "build": {
127
- "openclawVersion": "2026.8.1-beta.3",
127
+ "openclawVersion": "2026.9.1-beta.1",
128
128
  "bundledDist": false
129
129
  },
130
130
  "release": {
@@ -149,7 +149,7 @@
149
149
  "README.md"
150
150
  ],
151
151
  "peerDependencies": {
152
- "openclaw": ">=2026.8.1-beta.3"
152
+ "openclaw": ">=2026.9.1-beta.1"
153
153
  },
154
154
  "peerDependenciesMeta": {
155
155
  "openclaw": {