@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.
- package/dist/{channel-BZclM5wY.js → .setup/channel-SaGThQQW.mjs} +134 -193
- package/dist/.setup/channel-plugin-api-04wlnIps.mjs +3 -0
- package/dist/{channel-runtime-CRzAwKGK.js → .setup/channel-runtime-DBtfWzX8.mjs} +112 -325
- package/dist/{config-schema-BPoye3--.js → .setup/config-schema-BQXbFpTD.mjs} +43 -24
- package/dist/{runtime-xy-FcjJC.js → .setup/runtime-DZfYm3vY.mjs} +1 -1
- package/dist/.setup/secret-contract-DdKIs_mx.mjs +82 -0
- package/dist/.setup/secret-contract-api-CmA70kMR.mjs +3 -0
- package/dist/api.js +2 -2
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/configured-state.js +6 -0
- package/dist/runtime-api.js +1 -1
- package/dist/secret-contract-api.js +1 -1
- package/dist/setup-entry.js +3 -2
- package/openclaw.plugin.json +62 -72
- package/package.json +13 -91
- package/dist/doctor-contract-api.js +0 -16
- package/dist/secret-contract-D_DC3YWj.js +0 -42
|
@@ -1,30 +1,29 @@
|
|
|
1
|
-
import { t as IrcChannelConfigSchema } from "./config-schema-
|
|
2
|
-
import { t as getIrcRuntime } from "./runtime-
|
|
3
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
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 {
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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:
|
|
188
|
-
collectLists: (scope) =>
|
|
189
|
-
|
|
190
|
-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
799
|
-
const
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
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
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
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:
|
|
821
|
-
|
|
822
|
-
wildcardConfig,
|
|
823
|
-
hasConfiguredGroups: Object.keys(params.groups ?? {}).length > 0
|
|
827
|
+
allowed: false,
|
|
828
|
+
hasConfiguredGroups
|
|
824
829
|
};
|
|
825
830
|
}
|
|
826
|
-
function
|
|
827
|
-
|
|
828
|
-
return
|
|
829
|
-
|
|
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
|
|
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-
|
|
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
|
|
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
|
-
})
|
|
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
|
-
|
|
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
|
-
|
|
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: ({
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
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 {
|
|
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 };
|