@openclaw/irc 2026.7.2-beta.2 → 2026.7.2-beta.3

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 { g as resolveIrcAccount, h as resolveDefaultIrcAccountId, m as listIrcAccountIds, n as ircSetupWizard, p as listEnabledIrcAccounts, r as ircSetupAdapter, t as ircPlugin } from "./channel-DivPJINh.js";
1
+ import { g as resolveIrcAccount, h as resolveDefaultIrcAccountId, m as listIrcAccountIds, n as ircSetupWizard, p as listEnabledIrcAccounts, r as ircSetupAdapter, t as ircPlugin } from "./channel-BC0q2_Tg.js";
2
2
  import { n as setIrcRuntime } from "./runtime-xy-FcjJC.js";
3
3
  export { ircPlugin, ircSetupAdapter, ircSetupWizard, listEnabledIrcAccounts, listIrcAccountIds, resolveDefaultIrcAccountId, resolveIrcAccount, setIrcRuntime };
@@ -1,10 +1,10 @@
1
1
  import { t as IrcChannelConfigSchema } from "./config-schema-BPoye3--.js";
2
2
  import { t as getIrcRuntime } from "./runtime-xy-FcjJC.js";
3
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-PJHaoTSe.js";
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";
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, tryReadSecretFileSync } from "openclaw/plugin-sdk/channel-core";
7
+ import { buildChannelOutboundSessionRoute, createChatChannelPlugin, parseOptionalDelimitedEntries } from "openclaw/plugin-sdk/channel-core";
8
8
  import { buildMutableAllowEntryDetector, collectStandardAllowlistLists, composeAccountWarningCollectors, createAllowlistProviderOpenWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, resolveScopeKeyCaseInsensitive, resolveScopeRequireMention, resolveScopeToolsPolicy } 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";
@@ -12,6 +12,7 @@ import { buildBaseChannelStatusSummary, createComputedAccountStatusAdapter, crea
12
12
  import { DEFAULT_ACCOUNT_ID, DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
13
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";
15
16
  import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
16
17
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeStringifiedOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
17
18
  import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
@@ -66,11 +67,25 @@ function resolvePassword(accountId, merged) {
66
67
  };
67
68
  }
68
69
  if (merged.passwordFile?.trim()) {
69
- const filePassword = tryReadSecretFileSync(merged.passwordFile, "IRC password file", { rejectSymlink: true });
70
+ let diagnostic;
71
+ const filePassword = tryReadSecretFileSync(merged.passwordFile, "IRC password file", {
72
+ rejectSymlink: true,
73
+ credentialDiagnostic: {
74
+ configPath: `channels.irc.accounts.${accountId}.passwordFile`,
75
+ report: (value) => {
76
+ diagnostic = value;
77
+ }
78
+ }
79
+ });
70
80
  if (filePassword) return {
71
81
  password: filePassword,
72
82
  source: "passwordFile"
73
83
  };
84
+ return {
85
+ password: "",
86
+ source: "passwordFile",
87
+ diagnostic
88
+ };
74
89
  }
75
90
  const configPassword = normalizeResolvedSecretInputString({
76
91
  value: merged.password,
@@ -94,13 +109,25 @@ function resolveNickServConfig(accountId, nickserv) {
94
109
  value: base.password,
95
110
  path: `channels.irc.accounts.${accountId}.nickserv.password`
96
111
  }) || envPassword || "";
97
- if (!resolvedPassword && passwordFile) resolvedPassword = tryReadSecretFileSync(passwordFile, "IRC NickServ password file", { rejectSymlink: true }) ?? "";
112
+ let diagnostic;
113
+ if (!resolvedPassword && passwordFile) resolvedPassword = tryReadSecretFileSync(passwordFile, "IRC NickServ password file", {
114
+ rejectSymlink: true,
115
+ credentialDiagnostic: {
116
+ configPath: `channels.irc.accounts.${accountId}.nickserv.passwordFile`,
117
+ report: (value) => {
118
+ diagnostic = value;
119
+ }
120
+ }
121
+ }) ?? "";
98
122
  return {
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
+ config: {
124
+ ...base,
125
+ service: normalizeOptionalString(base.service),
126
+ passwordFile: passwordFile || void 0,
127
+ password: resolvedPassword || void 0,
128
+ registerEmail: base.registerEmail?.trim() || envRegisterEmail || void 0
129
+ },
130
+ diagnostic
104
131
  };
105
132
  }
106
133
  function resolveIrcAccount(params) {
@@ -119,7 +146,8 @@ function resolveIrcAccount(params) {
119
146
  const username = (merged.username?.trim() || (accountId === DEFAULT_ACCOUNT_ID ? process.env.IRC_USERNAME?.trim() : "") || nick || "openclaw").trim();
120
147
  const realname = (merged.realname?.trim() || (accountId === DEFAULT_ACCOUNT_ID ? process.env.IRC_REALNAME?.trim() : "") || "OpenClaw").trim();
121
148
  const passwordResolution = resolvePassword(accountId, merged);
122
- const nickserv = resolveNickServConfig(accountId, merged.nickserv);
149
+ const nickservResolution = resolveNickServConfig(accountId, merged.nickserv);
150
+ const diagnostics = [passwordResolution.diagnostic, nickservResolution.diagnostic].filter((diagnostic) => Boolean(diagnostic));
123
151
  const config = {
124
152
  ...merged,
125
153
  channels: merged.channels ?? envChannels,
@@ -129,7 +157,7 @@ function resolveIrcAccount(params) {
129
157
  nick,
130
158
  username,
131
159
  realname,
132
- nickserv
160
+ nickserv: nickservResolution.config
133
161
  };
134
162
  return {
135
163
  accountId,
@@ -144,6 +172,8 @@ function resolveIrcAccount(params) {
144
172
  realname,
145
173
  password: passwordResolution.password,
146
174
  passwordSource: passwordResolution.source,
175
+ tokenStatus: diagnostics.length > 0 ? "configured_unavailable" : passwordResolution.password || nickservResolution.config.password ? "available" : "missing",
176
+ ...diagnostics.length > 0 ? { credentialDiagnostics: diagnostics } : {},
147
177
  config
148
178
  };
149
179
  };
@@ -172,7 +202,7 @@ const collectIrcMutableAllowlistWarnings = createDangerousNameMatchingMutableAll
172
202
  });
173
203
  //#endregion
174
204
  //#region extensions/irc/src/gateway.ts
175
- const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-Dg0LFlsh.js"));
205
+ const loadIrcChannelRuntime$1 = createLazyRuntimeModule(() => import("./channel-runtime-DBNGrI_Y.js"));
176
206
  async function startIrcGatewayAccount(ctx) {
177
207
  const account = ctx.account;
178
208
  const statusSink = createAccountStatusSink({
@@ -1310,7 +1340,7 @@ const meta = {
1310
1340
  systemImage: "number",
1311
1341
  markdownCapable: true
1312
1342
  };
1313
- const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-Dg0LFlsh.js"));
1343
+ const loadIrcChannelRuntime = createLazyRuntimeModule(() => import("./channel-runtime-DBNGrI_Y.js"));
1314
1344
  function normalizePairingTarget(raw) {
1315
1345
  const normalized = normalizeIrcAllowEntry(raw);
1316
1346
  if (!normalized) return "";
@@ -1403,7 +1433,8 @@ const ircPlugin = createChatChannelPlugin({
1403
1433
  port: account.port,
1404
1434
  tls: account.tls,
1405
1435
  nick: account.nick,
1406
- passwordSource: account.passwordSource
1436
+ passwordSource: account.passwordSource,
1437
+ tokenStatus: account.tokenStatus
1407
1438
  }
1408
1439
  })
1409
1440
  },
@@ -1510,7 +1541,8 @@ const ircPlugin = createChatChannelPlugin({
1510
1541
  port: account.port,
1511
1542
  tls: account.tls,
1512
1543
  nick: account.nick,
1513
- passwordSource: account.passwordSource
1544
+ passwordSource: account.passwordSource,
1545
+ tokenStatus: account.tokenStatus
1514
1546
  }
1515
1547
  })
1516
1548
  }),
@@ -1,2 +1,2 @@
1
- import { t as ircPlugin } from "./channel-DivPJINh.js";
1
+ import { t as ircPlugin } from "./channel-BC0q2_Tg.js";
2
2
  export { ircPlugin };
@@ -1,13 +1,12 @@
1
- import { a as resolveIrcGroupRequireMention, c as isChannelTarget, d as connectIrcClient, f as makeIrcMessageId, g as resolveIrcAccount, i as resolveIrcGroupMatch, l as normalizeIrcAllowEntry, o as sendMessageIrc, s as buildIrcAllowlistCandidates, u as buildIrcConnectOptions } from "./channel-DivPJINh.js";
1
+ import { a as resolveIrcGroupRequireMention, c as isChannelTarget, d as connectIrcClient, f as makeIrcMessageId, g as resolveIrcAccount, i as resolveIrcGroupMatch, l as normalizeIrcAllowEntry, o as sendMessageIrc, s as buildIrcAllowlistCandidates, u as buildIrcConnectOptions } from "./channel-BC0q2_Tg.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 { resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
5
5
  import { resolveLoggerBackedRuntime } from "openclaw/plugin-sdk/extension-shared";
6
- import { logInboundDrop } from "openclaw/plugin-sdk/channel-inbound";
6
+ import { buildChannelInboundEventContext, logInboundDrop, resolveChannelInboundRouteEnvelope } from "openclaw/plugin-sdk/channel-inbound";
7
7
  import { channelIngressRoutes, createChannelIngressResolver, defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
8
8
  import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
9
9
  import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
10
- import { resolveInboundRouteEnvelopeBuilderWithRuntime } from "openclaw/plugin-sdk/inbound-envelope";
11
10
  import { deliverFormattedTextWithAttachments } from "openclaw/plugin-sdk/reply-payload";
12
11
  import { GROUP_POLICY_BLOCKED_LABEL, resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
13
12
  //#region extensions/irc/src/inbound.ts
@@ -253,19 +252,17 @@ async function handleIrcInbound(params) {
253
252
  }
254
253
  const channelTarget = message.target.startsWith("#") || message.target.startsWith("&") ? message.target : `#${message.target}`;
255
254
  const peerId = message.isGroup ? channelTarget : message.senderNick;
256
- const { route, buildEnvelope } = resolveInboundRouteEnvelopeBuilderWithRuntime({
255
+ const { route, buildEnvelope } = resolveChannelInboundRouteEnvelope({
257
256
  cfg: config,
258
257
  channel: CHANNEL_ID,
259
258
  accountId: account.accountId,
260
259
  peer: {
261
260
  kind: message.isGroup ? "group" : "direct",
262
261
  id: peerId
263
- },
264
- runtime: core.channel,
265
- sessionStore: config.session?.store
262
+ }
266
263
  });
267
264
  const fromLabel = message.isGroup ? message.target : senderDisplay;
268
- const { storePath, body } = buildEnvelope({
265
+ const body = buildEnvelope({
269
266
  channel: "IRC",
270
267
  from: fromLabel,
271
268
  timestamp: message.timestamp,
@@ -273,39 +270,58 @@ async function handleIrcInbound(params) {
273
270
  });
274
271
  const groupSystemPrompt = normalizeOptionalString(groupMatch.groupConfig?.systemPrompt);
275
272
  const blockStreamingEnabled = resolveChannelStreamingBlockEnabled(account.config);
276
- const ctxPayload = core.channel.reply.finalizeInboundContext({
277
- Body: body,
278
- RawBody: rawBody,
279
- CommandBody: rawBody,
280
- From: message.isGroup ? `channel:${channelTarget}` : `irc:${senderDisplay}`,
281
- To: message.isGroup ? `channel:${channelTarget}` : `irc:${peerId}`,
282
- SessionKey: route.sessionKey,
283
- AccountId: route.accountId,
284
- ChatType: message.isGroup ? "group" : "direct",
285
- ConversationLabel: fromLabel,
286
- SenderName: message.senderNick || void 0,
287
- SenderId: senderDisplay,
288
- GroupSubject: message.isGroup ? message.target : void 0,
289
- GroupSystemPrompt: message.isGroup ? groupSystemPrompt : void 0,
290
- Provider: CHANNEL_ID,
291
- Surface: CHANNEL_ID,
292
- WasMentioned: message.isGroup ? wasMentioned : void 0,
293
- MessageSid: message.messageId,
294
- Timestamp: message.timestamp,
295
- OriginatingChannel: CHANNEL_ID,
296
- OriginatingTo: message.isGroup ? `channel:${channelTarget}` : `irc:${peerId}`,
297
- CommandAuthorized: commandAuthorized
273
+ const ctxPayload = buildChannelInboundEventContext({
274
+ channel: CHANNEL_ID,
275
+ accountId: route.accountId,
276
+ messageId: message.messageId,
277
+ timestamp: message.timestamp,
278
+ from: message.isGroup ? `channel:${channelTarget}` : `irc:${senderDisplay}`,
279
+ sender: {
280
+ id: senderDisplay,
281
+ name: message.senderNick || void 0
282
+ },
283
+ conversation: {
284
+ kind: message.isGroup ? "group" : "direct",
285
+ id: peerId,
286
+ label: fromLabel
287
+ },
288
+ route: {
289
+ agentId: route.agentId,
290
+ dmScope: route.dmScope,
291
+ accountId: route.accountId,
292
+ routeSessionKey: route.sessionKey
293
+ },
294
+ reply: {
295
+ to: message.isGroup ? `channel:${channelTarget}` : `irc:${peerId}`,
296
+ originatingTo: message.isGroup ? `channel:${channelTarget}` : `irc:${peerId}`
297
+ },
298
+ message: {
299
+ body,
300
+ bodyForAgent: rawBody,
301
+ rawBody,
302
+ commandBody: rawBody
303
+ },
304
+ access: {
305
+ commands: { authorized: commandAuthorized },
306
+ mentions: {
307
+ canDetectMention: message.isGroup,
308
+ wasMentioned
309
+ }
310
+ },
311
+ extra: {
312
+ GroupSubject: message.isGroup ? message.target : void 0,
313
+ GroupSystemPrompt: message.isGroup ? groupSystemPrompt : void 0
314
+ }
298
315
  });
299
- await core.channel.inbound.dispatchReply({
316
+ await core.channel.inbound.dispatch({
300
317
  cfg: config,
301
318
  channel: CHANNEL_ID,
302
319
  accountId: account.accountId,
303
- agentId: route.agentId,
304
- routeSessionKey: route.sessionKey,
305
- storePath,
320
+ route: {
321
+ agentId: route.agentId,
322
+ sessionKey: route.sessionKey
323
+ },
306
324
  ctxPayload,
307
- recordInboundSession: core.channel.session.recordInboundSession,
308
- dispatchReplyWithBufferedBlockDispatcher: core.channel.reply.dispatchReplyWithBufferedBlockDispatcher,
309
325
  delivery: {
310
326
  deliver: async (payload) => {
311
327
  await deliverIrcReply({
@@ -28,6 +28,7 @@ function collectRuntimeConfigAssignments(params) {
28
28
  defaults: params.defaults,
29
29
  context: params.context,
30
30
  topLevelActive: isBaseFieldActiveForChannelSurface(surface, "nickserv") && isRecord(irc.nickserv) && isEnabledFlag(irc.nickserv),
31
+ topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !Object.hasOwn(account, "nickserv") && isEnabledFlag(irc.nickserv),
31
32
  topInactiveReason: "no enabled account inherits this top-level IRC nickserv config or NickServ is disabled.",
32
33
  accountActive: ({ account, enabled }) => enabled && isRecord(account.nickserv) && isEnabledFlag(account.nickserv),
33
34
  accountInactiveReason: "IRC account is disabled or NickServ is disabled for this account."
@@ -1,2 +1,2 @@
1
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-PJHaoTSe.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-D_DC3YWj.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/irc",
3
- "version": "2026.7.2-beta.2",
3
+ "version": "2026.7.2-beta.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/irc",
9
- "version": "2026.7.2-beta.2",
9
+ "version": "2026.7.2-beta.3",
10
10
  "dependencies": {
11
11
  "zod": "4.4.3"
12
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/irc",
3
- "version": "2026.7.2-beta.2",
3
+ "version": "2026.7.2-beta.3",
4
4
  "description": "OpenClaw IRC channel plugin",
5
5
  "type": "module",
6
6
  "openclaw": {
@@ -37,10 +37,10 @@
37
37
  }
38
38
  },
39
39
  "compat": {
40
- "pluginApi": ">=2026.7.2-beta.2"
40
+ "pluginApi": ">=2026.7.2-beta.3"
41
41
  },
42
42
  "build": {
43
- "openclawVersion": "2026.7.2-beta.2",
43
+ "openclawVersion": "2026.7.2-beta.3",
44
44
  "bundledDist": false
45
45
  },
46
46
  "release": {
@@ -66,7 +66,7 @@
66
66
  "README.md"
67
67
  ],
68
68
  "peerDependencies": {
69
- "openclaw": ">=2026.7.2-beta.2"
69
+ "openclaw": ">=2026.7.2-beta.3"
70
70
  },
71
71
  "peerDependenciesMeta": {
72
72
  "openclaw": {