@openclaw/irc 2026.7.2-beta.5 → 2026.7.33

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.
@@ -1,30 +1,29 @@
1
- import { t as IrcChannelConfigSchema } from "./config-schema-BPoye3--.js";
2
- import { t as getIrcRuntime } from "./runtime-xy-FcjJC.js";
3
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-D_DC3YWj.js";
1
+ import { t as IrcChannelConfigSchema } from "./config-schema-BQXbFpTD.mjs";
2
+ import { t as getIrcRuntime } from "./runtime-DZfYm3vY.mjs";
3
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DdKIs_mx.mjs";
4
4
  import { createAccountListHelpers, describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
5
5
  import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
6
6
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
7
- import { buildChannelOutboundSessionRoute, createChatChannelPlugin, parseOptionalDelimitedEntries } from "openclaw/plugin-sdk/channel-core";
8
- import { buildMutableAllowEntryDetector, collectStandardAllowlistLists, composeAccountWarningCollectors, createAllowlistProviderOpenWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, resolveScopeKeyCaseInsensitive, resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
7
+ import { buildChannelOutboundSessionRoute, createChatChannelPlugin, parseOptionalDelimitedEntries, tryReadSecretFileSync } from "openclaw/plugin-sdk/channel-core";
8
+ import { composeAccountWarningCollectors, createAllowlistProviderOpenWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy";
9
9
  import { createChannelDirectoryAdapter, createResolvedDirectoryEntriesLister } from "openclaw/plugin-sdk/directory-runtime";
10
10
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
11
11
  import { buildBaseChannelStatusSummary, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
12
- import { resolveAccountWithDefaultFallback } from "openclaw/plugin-sdk/account-core";
13
12
  import { DEFAULT_ACCOUNT_ID, DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
13
+ import { resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
14
14
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
15
- import { tryReadSecretFileSync } from "openclaw/plugin-sdk/secret-file-runtime";
16
15
  import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
17
16
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeStringifiedOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
18
- import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, runPassiveAccountLifecycle, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
17
+ import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
19
18
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
20
19
  import { chunkTextForOutbound, convertMarkdownTables, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
20
+ import { runStoppablePassiveMonitor } from "openclaw/plugin-sdk/extension-shared";
21
21
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
22
22
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
23
23
  import net from "node:net";
24
24
  import tls from "node:tls";
25
25
  import { withTimeout } from "openclaw/plugin-sdk/security-runtime";
26
26
  import { randomUUID } from "node:crypto";
27
- import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
28
27
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1 } from "openclaw/plugin-sdk/routing";
29
28
  import { applyAccountNameToChannelSection, createAllowFromSection, createPromptParsedAllowFromForAccount, createSetupInputPresenceValidator, createSetupTranslator, createStandardChannelSetupStatus, createTopLevelChannelAllowFromSetter, createTopLevelChannelDmPolicySetter, formatDocsLink, patchScopedAccountConfig, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
30
29
  //#region extensions/irc/src/accounts.ts
@@ -44,12 +43,20 @@ function parseIntEnv(value) {
44
43
  if (parsed === void 0 || parsed > 65535) return;
45
44
  return parsed;
46
45
  }
47
- const { listAccountIds: listIrcAccountIds, resolveDefaultAccountId: resolveDefaultIrcAccountId, resolveAccountConfig: mergeIrcAccountConfig } = createAccountListHelpers("irc", {
46
+ const { listAccountIds: listIrcAccountIds, resolveDefaultAccountId: resolveDefaultIrcAccountId } = createAccountListHelpers("irc", {
48
47
  normalizeAccountId,
49
- omitKeys: ["defaultAccount"],
50
- nestedObjectKeys: ["nickserv"],
51
48
  hasImplicitDefaultAccount: (cfg) => Boolean((cfg.channels?.irc?.host?.trim() || process.env.IRC_HOST?.trim()) && (cfg.channels?.irc?.nick?.trim() || process.env.IRC_NICK?.trim()))
52
49
  });
50
+ function mergeIrcAccountConfig(cfg, accountId) {
51
+ return resolveMergedAccountConfig({
52
+ channelConfig: cfg.channels?.irc,
53
+ accounts: cfg.channels?.irc?.accounts,
54
+ accountId,
55
+ omitKeys: ["defaultAccount"],
56
+ normalizeAccountId,
57
+ nestedObjectKeys: ["nickserv"]
58
+ });
59
+ }
53
60
  function resolvePassword(accountId, merged) {
54
61
  if (accountId === DEFAULT_ACCOUNT_ID) {
55
62
  const envPassword = process.env.IRC_PASSWORD?.trim();
@@ -59,25 +66,11 @@ function resolvePassword(accountId, merged) {
59
66
  };
60
67
  }
61
68
  if (merged.passwordFile?.trim()) {
62
- let diagnostic;
63
- const filePassword = tryReadSecretFileSync(merged.passwordFile, "IRC password file", {
64
- rejectSymlink: true,
65
- credentialDiagnostic: {
66
- configPath: `channels.irc.accounts.${accountId}.passwordFile`,
67
- report: (value) => {
68
- diagnostic = value;
69
- }
70
- }
71
- });
69
+ const filePassword = tryReadSecretFileSync(merged.passwordFile, "IRC password file", { rejectSymlink: true });
72
70
  if (filePassword) return {
73
71
  password: filePassword,
74
72
  source: "passwordFile"
75
73
  };
76
- return {
77
- password: "",
78
- source: "passwordFile",
79
- diagnostic
80
- };
81
74
  }
82
75
  const configPassword = normalizeResolvedSecretInputString({
83
76
  value: merged.password,
@@ -101,28 +94,17 @@ function resolveNickServConfig(accountId, nickserv) {
101
94
  value: base.password,
102
95
  path: `channels.irc.accounts.${accountId}.nickserv.password`
103
96
  }) || envPassword || "";
104
- let diagnostic;
105
- if (!resolvedPassword && passwordFile) resolvedPassword = tryReadSecretFileSync(passwordFile, "IRC NickServ password file", {
106
- rejectSymlink: true,
107
- credentialDiagnostic: {
108
- configPath: `channels.irc.accounts.${accountId}.nickserv.passwordFile`,
109
- report: (value) => {
110
- diagnostic = value;
111
- }
112
- }
113
- }) ?? "";
97
+ if (!resolvedPassword && passwordFile) resolvedPassword = tryReadSecretFileSync(passwordFile, "IRC NickServ password file", { rejectSymlink: true }) ?? "";
114
98
  return {
115
- config: {
116
- ...base,
117
- service: normalizeOptionalString(base.service),
118
- passwordFile: passwordFile || void 0,
119
- password: resolvedPassword || void 0,
120
- registerEmail: base.registerEmail?.trim() || envRegisterEmail || void 0
121
- },
122
- diagnostic
99
+ ...base,
100
+ service: normalizeOptionalString(base.service),
101
+ passwordFile: passwordFile || void 0,
102
+ password: resolvedPassword || void 0,
103
+ registerEmail: base.registerEmail?.trim() || envRegisterEmail || void 0
123
104
  };
124
105
  }
125
106
  function resolveIrcAccount(params) {
107
+ const hasExplicitAccountId = Boolean(params.accountId?.trim());
126
108
  const baseEnabled = params.cfg.channels?.irc?.enabled !== false;
127
109
  const resolve = (accountId) => {
128
110
  const merged = mergeIrcAccountConfig(params.cfg, accountId);
@@ -137,8 +119,7 @@ function resolveIrcAccount(params) {
137
119
  const username = (merged.username?.trim() || (accountId === DEFAULT_ACCOUNT_ID ? process.env.IRC_USERNAME?.trim() : "") || nick || "openclaw").trim();
138
120
  const realname = (merged.realname?.trim() || (accountId === DEFAULT_ACCOUNT_ID ? process.env.IRC_REALNAME?.trim() : "") || "OpenClaw").trim();
139
121
  const passwordResolution = resolvePassword(accountId, merged);
140
- const nickservResolution = resolveNickServConfig(accountId, merged.nickserv);
141
- const diagnostics = [passwordResolution.diagnostic, nickservResolution.diagnostic].filter((diagnostic) => Boolean(diagnostic));
122
+ const nickserv = resolveNickServConfig(accountId, merged.nickserv);
142
123
  const config = {
143
124
  ...merged,
144
125
  channels: merged.channels ?? envChannels,
@@ -148,7 +129,7 @@ function resolveIrcAccount(params) {
148
129
  nick,
149
130
  username,
150
131
  realname,
151
- nickserv: nickservResolution.config
132
+ nickserv
152
133
  };
153
134
  return {
154
135
  accountId,
@@ -163,18 +144,17 @@ function resolveIrcAccount(params) {
163
144
  realname,
164
145
  password: passwordResolution.password,
165
146
  passwordSource: passwordResolution.source,
166
- tokenStatus: diagnostics.length > 0 ? "configured_unavailable" : passwordResolution.password || nickservResolution.config.password ? "available" : "missing",
167
- ...diagnostics.length > 0 ? { credentialDiagnostics: diagnostics } : {},
168
147
  config
169
148
  };
170
149
  };
171
- return resolveAccountWithDefaultFallback({
172
- accountId: params.accountId,
173
- normalizeAccountId,
174
- resolvePrimary: resolve,
175
- hasCredential: (account) => account.configured,
176
- resolveDefaultAccountId: () => resolveDefaultIrcAccountId(params.cfg)
177
- });
150
+ const primary = resolve(normalizeAccountId(params.accountId));
151
+ if (hasExplicitAccountId) return primary;
152
+ if (primary.configured) return primary;
153
+ const fallbackId = resolveDefaultIrcAccountId(params.cfg);
154
+ if (fallbackId === primary.accountId) return primary;
155
+ const fallback = resolve(fallbackId);
156
+ if (!fallback.configured) return primary;
157
+ return fallback;
178
158
  }
179
159
  function listEnabledIrcAccounts(cfg) {
180
160
  return listIrcAccountIds(cfg).map((accountId) => resolveIrcAccount({
@@ -182,17 +162,42 @@ function listEnabledIrcAccounts(cfg) {
182
162
  accountId
183
163
  })).filter((account) => account.enabled);
184
164
  }
165
+ //#endregion
166
+ //#region extensions/irc/src/doctor.ts
167
+ function asObjectRecord(value) {
168
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
169
+ }
170
+ function isIrcMutableAllowEntry(raw) {
171
+ const text = normalizeLowercaseStringOrEmpty(raw);
172
+ if (!text || text === "*") return false;
173
+ return !text.replace(/^irc:/, "").replace(/^user:/, "").trim().includes("@");
174
+ }
185
175
  const collectIrcMutableAllowlistWarnings = createDangerousNameMatchingMutableAllowlistWarningCollector({
186
176
  channel: "irc",
187
- detector: buildMutableAllowEntryDetector({ stableIdPattern: /^(?:(?:irc|user):)*[^@]*@/i }),
188
- collectLists: (scope) => collectStandardAllowlistLists(scope, {
189
- includeGroups: true,
190
- groupField: "allowFrom"
191
- })
177
+ detector: isIrcMutableAllowEntry,
178
+ collectLists: (scope) => {
179
+ const lists = [{
180
+ pathLabel: `${scope.prefix}.allowFrom`,
181
+ list: scope.account.allowFrom
182
+ }, {
183
+ pathLabel: `${scope.prefix}.groupAllowFrom`,
184
+ list: scope.account.groupAllowFrom
185
+ }];
186
+ const groups = asObjectRecord(scope.account.groups);
187
+ if (groups) for (const [groupKey, groupRaw] of Object.entries(groups)) {
188
+ const group = asObjectRecord(groupRaw);
189
+ if (!group) continue;
190
+ lists.push({
191
+ pathLabel: `${scope.prefix}.groups.${groupKey}.allowFrom`,
192
+ list: group.allowFrom
193
+ });
194
+ }
195
+ return lists;
196
+ }
192
197
  });
193
198
  //#endregion
194
199
  //#region extensions/irc/src/gateway.ts
195
- const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-CRzAwKGK.js"));
200
+ const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-DBtfWzX8.mjs"));
196
201
  async function startIrcGatewayAccount(ctx) {
197
202
  const account = ctx.account;
198
203
  const statusSink = createAccountStatusSink({
@@ -202,7 +207,7 @@ async function startIrcGatewayAccount(ctx) {
202
207
  if (!account.configured) throw new Error(`IRC is not configured for account "${account.accountId}" (need host and nick in channels.irc).`);
203
208
  ctx.log?.info?.(`[${account.accountId}] starting IRC provider (${account.host}:${account.port}${account.tls ? " tls" : ""})`);
204
209
  const { monitorIrcProvider } = await loadIrcChannelRuntime$1();
205
- await runPassiveAccountLifecycle({
210
+ await runStoppablePassiveMonitor({
206
211
  abortSignal: ctx.abortSignal,
207
212
  start: async () => await monitorIrcProvider({
208
213
  accountId: account.accountId,
@@ -210,10 +215,7 @@ async function startIrcGatewayAccount(ctx) {
210
215
  runtime: ctx.runtime,
211
216
  abortSignal: ctx.abortSignal,
212
217
  statusSink
213
- }),
214
- stop: async (monitor) => {
215
- await monitor.stop();
216
- }
218
+ })
217
219
  });
218
220
  }
219
221
  //#endregion
@@ -547,7 +549,7 @@ async function connectIrcClient(options) {
547
549
  if (line.command === "PRIVMSG") {
548
550
  const targetParam = line.params[0];
549
551
  const target = targetParam ? targetParam.trim() : "";
550
- const text = line.trailing ?? line.params[1] ?? "";
552
+ const text = line.trailing != null ? line.trailing : "";
551
553
  const prefix = parseIrcPrefix(line.prefix);
552
554
  const senderNick = prefix.nick ? prefix.nick.trim() : "";
553
555
  if (!target || !senderNick || !text.trim()) continue;
@@ -555,7 +557,6 @@ async function connectIrcClient(options) {
555
557
  senderNick,
556
558
  senderUser: prefix.user ? prefix.user.trim() : void 0,
557
559
  senderHost: prefix.host ? prefix.host.trim() : void 0,
558
- connectedNick: currentNick,
559
560
  target,
560
561
  text,
561
562
  rawLine
@@ -795,47 +796,42 @@ const ircOutboundBaseAdapter = {
795
796
  };
796
797
  //#endregion
797
798
  //#region extensions/irc/src/policy.ts
798
- function resolveIrcGroupScope(params) {
799
- const { "*": wildcard, ...groups } = params.groups ?? {};
800
- const project = (entry) => ({
801
- requireMention: entry.requireMention,
802
- tools: entry.tools
803
- });
804
- const tree = {
805
- defaults: wildcard ? project(wildcard) : void 0,
806
- scopes: Object.fromEntries(Object.entries(groups).map(([key, entry]) => [key, project(entry)]))
799
+ function resolveIrcGroupMatch(params) {
800
+ const groups = params.groups ?? {};
801
+ const hasConfiguredGroups = Object.keys(groups).length > 0;
802
+ const direct = groups[params.target];
803
+ if (direct) return {
804
+ allowed: true,
805
+ groupConfig: direct,
806
+ wildcardConfig: groups["*"],
807
+ hasConfiguredGroups
807
808
  };
808
- const key = resolveScopeKeyCaseInsensitive(tree, params.target);
809
- return {
810
- tree,
811
- path: key ? [key] : []
809
+ const targetLower = normalizeLowercaseStringOrEmpty(params.target);
810
+ const directKey = Object.keys(groups).find((key) => normalizeLowercaseStringOrEmpty(key) === targetLower);
811
+ if (directKey) {
812
+ const matched = groups[directKey];
813
+ if (matched) return {
814
+ allowed: true,
815
+ groupConfig: matched,
816
+ wildcardConfig: groups["*"],
817
+ hasConfiguredGroups
818
+ };
819
+ }
820
+ const wildcard = groups["*"];
821
+ if (wildcard) return {
822
+ allowed: true,
823
+ wildcardConfig: wildcard,
824
+ hasConfiguredGroups
812
825
  };
813
- }
814
- function resolveIrcGroupMatch(params) {
815
- const { path } = resolveIrcGroupScope(params);
816
- const key = path[0];
817
- const groupConfig = key ? params.groups?.[key] : void 0;
818
- const wildcardConfig = params.groups?.["*"];
819
826
  return {
820
- allowed: Boolean(groupConfig ?? wildcardConfig),
821
- groupConfig,
822
- wildcardConfig,
823
- hasConfiguredGroups: Object.keys(params.groups ?? {}).length > 0
827
+ allowed: false,
828
+ hasConfiguredGroups
824
829
  };
825
830
  }
826
- function resolveIrcGroupRequireMention(params) {
827
- const { tree, path } = resolveIrcGroupScope(params);
828
- return resolveScopeRequireMention({
829
- tree,
830
- path
831
- });
832
- }
833
- function resolveIrcGroupToolPolicy(params) {
834
- const { tree, path } = resolveIrcGroupScope(params);
835
- return resolveScopeToolsPolicy({
836
- tree,
837
- path
838
- });
831
+ function resolveIrcRequireMention(params) {
832
+ if (params.groupConfig?.requireMention !== void 0) return params.groupConfig.requireMention;
833
+ if (params.wildcardConfig?.requireMention !== void 0) return params.wildcardConfig.requireMention;
834
+ return true;
839
835
  }
840
836
  //#endregion
841
837
  //#region extensions/irc/src/probe.ts
@@ -933,7 +929,6 @@ function setIrcGroupAccess(cfg, accountId, policy, entries, normalizeGroupEntry)
933
929
  });
934
930
  }
935
931
  const ircSetupAdapter = {
936
- singleAccountKeysToMove: ["password"],
937
932
  resolveAccountId: ({ accountId }) => normalizeAccountId$1(accountId),
938
933
  applyAccountName: ({ cfg, accountId, name }) => applyAccountNameToChannelSection({
939
934
  cfg,
@@ -970,75 +965,6 @@ const ircSetupAdapter = {
970
965
  });
971
966
  }
972
967
  };
973
- const ircSetupContract = defineChannelSetupContract({
974
- fields: {
975
- host: {
976
- kind: "string",
977
- cli: {
978
- flags: "--host <host>",
979
- description: "IRC server host"
980
- }
981
- },
982
- port: {
983
- kind: "string",
984
- cli: {
985
- flags: "--port <port>",
986
- description: "IRC server port"
987
- }
988
- },
989
- tls: {
990
- kind: "boolean",
991
- cli: {
992
- flags: "--tls",
993
- description: "Use TLS for IRC"
994
- }
995
- },
996
- nick: {
997
- kind: "string",
998
- cli: {
999
- flags: "--nick <nick>",
1000
- description: "IRC nickname"
1001
- }
1002
- },
1003
- username: {
1004
- kind: "string",
1005
- cli: {
1006
- flags: "--username <name>",
1007
- description: "IRC username"
1008
- }
1009
- },
1010
- realname: {
1011
- kind: "string",
1012
- cli: {
1013
- flags: "--realname <name>",
1014
- description: "IRC real name"
1015
- }
1016
- },
1017
- channels: {
1018
- kind: "string-list",
1019
- cli: {
1020
- flags: "--channels <names>",
1021
- description: "IRC channels"
1022
- }
1023
- },
1024
- password: {
1025
- kind: "string",
1026
- sensitive: true,
1027
- cli: {
1028
- flags: "--password <password>",
1029
- description: "IRC server password"
1030
- }
1031
- },
1032
- useEnv: {
1033
- kind: "boolean",
1034
- cli: {
1035
- flags: "--use-env",
1036
- description: "Use IRC environment configuration"
1037
- }
1038
- }
1039
- },
1040
- legacyAdapter: ircSetupAdapter
1041
- });
1042
968
  //#endregion
1043
969
  //#region extensions/irc/src/setup-surface.ts
1044
970
  const t = createSetupTranslator();
@@ -1232,7 +1158,8 @@ const ircSetupWizard = {
1232
1158
  return String(defaultPort);
1233
1159
  },
1234
1160
  validate: ({ value }) => {
1235
- const parsed = parseStrictPositiveInteger(normalizeStringifiedOptionalString(value) ?? "");
1161
+ const raw = normalizeStringifiedOptionalString(value) ?? "";
1162
+ const parsed = parseStrictPositiveInteger(raw);
1236
1163
  return parsed !== void 0 && parsed <= 65535 ? void 0 : "Use a port between 1 and 65535";
1237
1164
  },
1238
1165
  normalizeValue: ({ value }) => String(parsePort(value, 6697)),
@@ -1404,7 +1331,7 @@ const meta = {
1404
1331
  systemImage: "number",
1405
1332
  markdownCapable: true
1406
1333
  };
1407
- const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-CRzAwKGK.js"));
1334
+ const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-DBtfWzX8.mjs"));
1408
1335
  function normalizePairingTarget(raw) {
1409
1336
  const normalized = normalizeIrcAllowEntry(raw);
1410
1337
  if (!normalized) return "";
@@ -1460,7 +1387,7 @@ const resolveIrcDmPolicy = createScopedDmSecurityResolver({
1460
1387
  policyPathSuffix: "dmPolicy",
1461
1388
  normalizeEntry: (raw) => normalizeIrcAllowEntry(raw)
1462
1389
  });
1463
- const collectIrcSecurityWarnings = composeAccountWarningCollectors(createAllowlistProviderOpenWarningCollector({
1390
+ const collectIrcGroupPolicyWarnings = createAllowlistProviderOpenWarningCollector({
1464
1391
  providerConfigPresent: (cfg) => cfg.channels?.irc !== void 0,
1465
1392
  resolveGroupPolicy: (account) => account.config.groupPolicy,
1466
1393
  buildOpenWarning: {
@@ -1468,7 +1395,8 @@ const collectIrcSecurityWarnings = composeAccountWarningCollectors(createAllowli
1468
1395
  openBehavior: "allows all channels and senders (mention-gated)",
1469
1396
  remediation: "Prefer channels.irc.groupPolicy=\"allowlist\" with channels.irc.groups"
1470
1397
  }
1471
- }), (account) => !account.config.tls && "- IRC TLS is disabled (channels.irc.tls=false); traffic and credentials are plaintext.", (account) => account.config.nickserv?.register && "- IRC NickServ registration is enabled (channels.irc.nickserv.register=true); this sends \"REGISTER\" on every connect. Disable after first successful registration.", (account) => account.config.nickserv?.register && !account.config.nickserv.password?.trim() && "- IRC NickServ registration is enabled but no NickServ password is resolved; set channels.irc.nickserv.password, channels.irc.nickserv.passwordFile, or IRC_NICKSERV_PASSWORD.");
1398
+ });
1399
+ const collectIrcSecurityWarnings = composeAccountWarningCollectors(collectIrcGroupPolicyWarnings, (account) => !account.config.tls && "- IRC TLS is disabled (channels.irc.tls=false); traffic and credentials are plaintext.", (account) => account.config.nickserv?.register && "- IRC NickServ registration is enabled (channels.irc.nickserv.register=true); this sends \"REGISTER\" on every connect. Disable after first successful registration.", (account) => account.config.nickserv?.register && !account.config.nickserv.password?.trim() && "- IRC NickServ registration is enabled but no NickServ password is resolved; set channels.irc.nickserv.password, channels.irc.nickserv.passwordFile, or IRC_NICKSERV_PASSWORD.");
1472
1400
  const ircPlugin = createChatChannelPlugin({
1473
1401
  base: {
1474
1402
  id: "irc",
@@ -1477,7 +1405,6 @@ const ircPlugin = createChatChannelPlugin({
1477
1405
  quickstartAllowFrom: true
1478
1406
  },
1479
1407
  setup: ircSetupAdapter,
1480
- setupContract: ircSetupContract,
1481
1408
  setupWizard: ircSetupWizard,
1482
1409
  capabilities: {
1483
1410
  chatTypes: ["direct", "group"],
@@ -1498,8 +1425,7 @@ const ircPlugin = createChatChannelPlugin({
1498
1425
  port: account.port,
1499
1426
  tls: account.tls,
1500
1427
  nick: account.nick,
1501
- passwordSource: account.passwordSource,
1502
- tokenStatus: account.tokenStatus
1428
+ passwordSource: account.passwordSource
1503
1429
  }
1504
1430
  })
1505
1431
  },
@@ -1518,10 +1444,14 @@ const ircPlugin = createChatChannelPlugin({
1518
1444
  accountId
1519
1445
  });
1520
1446
  if (!groupId) return true;
1521
- return resolveIrcGroupRequireMention({
1447
+ const match = resolveIrcGroupMatch({
1522
1448
  groups: account.config.groups,
1523
1449
  target: groupId
1524
1450
  });
1451
+ return resolveIrcRequireMention({
1452
+ groupConfig: match.groupConfig,
1453
+ wildcardConfig: match.wildcardConfig
1454
+ });
1525
1455
  },
1526
1456
  resolveToolPolicy: ({ cfg, accountId, groupId }) => {
1527
1457
  const account = resolveIrcAccount({
@@ -1529,10 +1459,11 @@ const ircPlugin = createChatChannelPlugin({
1529
1459
  accountId
1530
1460
  });
1531
1461
  if (!groupId) return;
1532
- return resolveIrcGroupToolPolicy({
1462
+ const match = resolveIrcGroupMatch({
1533
1463
  groups: account.config.groups,
1534
1464
  target: groupId
1535
1465
  });
1466
+ return match.groupConfig?.tools ?? match.wildcardConfig?.tools;
1536
1467
  }
1537
1468
  },
1538
1469
  messaging: {
@@ -1606,8 +1537,7 @@ const ircPlugin = createChatChannelPlugin({
1606
1537
  port: account.port,
1607
1538
  tls: account.tls,
1608
1539
  nick: account.nick,
1609
- passwordSource: account.passwordSource,
1610
- tokenStatus: account.tokenStatus
1540
+ passwordSource: account.passwordSource
1611
1541
  }
1612
1542
  })
1613
1543
  }),
@@ -1635,13 +1565,24 @@ const ircPlugin = createChatChannelPlugin({
1635
1565
  base: ircOutboundBaseAdapter,
1636
1566
  attachedResults: {
1637
1567
  channel: "irc",
1638
- sendText: ({ onDeliveryResult: _onDeliveryResult, ...ctx }) => ircMessageAdapter.send.text(ctx),
1639
- sendMedia: ({ onDeliveryResult: _onDeliveryResult, mediaUrl, ...ctx }) => ircMessageAdapter.send.media({
1640
- ...ctx,
1641
- mediaUrl: mediaUrl ?? ""
1642
- })
1568
+ sendText: async ({ cfg, to, text, accountId, replyToId }) => {
1569
+ const { sendMessageIrc } = await loadIrcChannelRuntime();
1570
+ return await sendMessageIrc(to, text, {
1571
+ cfg,
1572
+ accountId: accountId ?? void 0,
1573
+ replyTo: replyToId ?? void 0
1574
+ });
1575
+ },
1576
+ sendMedia: async ({ cfg, to, text, mediaUrl, accountId, replyToId }) => {
1577
+ const { sendMessageIrc } = await loadIrcChannelRuntime();
1578
+ return await sendMessageIrc(to, mediaUrl ? `${text}\n\nAttachment: ${mediaUrl}` : text, {
1579
+ cfg,
1580
+ accountId: accountId ?? void 0,
1581
+ replyTo: replyToId ?? void 0
1582
+ });
1583
+ }
1643
1584
  }
1644
1585
  }
1645
1586
  });
1646
1587
  //#endregion
1647
- export { resolveIrcAccount as _, resolveIrcGroupRequireMention as a, isChannelTarget as c, connectIrcClient as d, parseIrcLine as f, resolveDefaultIrcAccountId as g, listIrcAccountIds as h, resolveIrcGroupMatch as i, normalizeIrcAllowEntry as l, listEnabledIrcAccounts as m, ircSetupWizard as n, sendMessageIrc as o, parseIrcPrefix as p, ircSetupAdapter as r, buildIrcAllowlistCandidates as s, ircPlugin as t, buildIrcConnectOptions as u };
1588
+ export { resolveIrcRequireMention as a, isChannelTarget as c, connectIrcClient as d, makeIrcMessageId as f, resolveIrcAccount as g, resolveDefaultIrcAccountId as h, resolveIrcGroupMatch as i, normalizeIrcAllowEntry as l, listIrcAccountIds as m, ircSetupWizard as n, sendMessageIrc as o, listEnabledIrcAccounts as p, ircSetupAdapter as r, buildIrcAllowlistCandidates as s, ircPlugin as t, buildIrcConnectOptions as u };
@@ -0,0 +1,3 @@
1
+ import { t as ircPlugin } from "./channel-SaGThQQW.mjs";
2
+ import "../channel-plugin-api.js";
3
+ export { ircPlugin };