Fix IRC proactive sends: use monitor's persistent client
The sendMessageIrc function was creating transient IRC connections for proactive sends. These transient clients don't join channels before sending PRIVMSG, so messages to channels silently fail. This adds an active client registry that the monitor populates when it connects. sendMessageIrc now checks for an active persistent client first, falling back to transient connections only when no monitor client is available. This enables agents to initiate conversations in IRC channels from their main session — a prerequisite for autonomy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dc86b6d72a
commit
922cba6775
24
extensions/irc/src/active-clients.ts
Normal file
24
extensions/irc/src/active-clients.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import type { IrcClient } from "./client.js";
|
||||
|
||||
/**
|
||||
* Registry of active IRC clients from the monitor.
|
||||
* Keyed by accountId. Allows sendMessageIrc to use the persistent
|
||||
* monitor client instead of creating a transient connection.
|
||||
*/
|
||||
const activeClients = new Map<string, IrcClient>();
|
||||
|
||||
export function setActiveClient(accountId: string, client: IrcClient): void {
|
||||
activeClients.set(accountId, client);
|
||||
}
|
||||
|
||||
export function getActiveClient(accountId: string): IrcClient | undefined {
|
||||
const client = activeClients.get(accountId);
|
||||
if (client && client.isReady()) {
|
||||
return client;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function removeActiveClient(accountId: string): void {
|
||||
activeClients.delete(accountId);
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import { resolveLoggerBackedRuntime } from "openclaw/plugin-sdk/extension-shared";
|
||||
import { resolveIrcAccount } from "./accounts.js";
|
||||
import { setActiveClient, removeActiveClient } from "./active-clients.js";
|
||||
import { connectIrcClient, type IrcClient } from "./client.js";
|
||||
import { buildIrcConnectOptions } from "./connect-options.js";
|
||||
import { handleIrcInbound } from "./inbound.js";
|
||||
@ -136,8 +137,11 @@ export async function monitorIrcProvider(opts: IrcMonitorOptions): Promise<{ sto
|
||||
`[${account.accountId}] connected to ${account.host}:${account.port}${account.tls ? " (tls)" : ""} as ${client.nick}`,
|
||||
);
|
||||
|
||||
setActiveClient(account.accountId, client);
|
||||
|
||||
return {
|
||||
stop: () => {
|
||||
removeActiveClient(account.accountId);
|
||||
client?.quit("shutdown");
|
||||
client = null;
|
||||
},
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { resolveIrcAccount } from "./accounts.js";
|
||||
import { getActiveClient } from "./active-clients.js";
|
||||
import type { IrcClient } from "./client.js";
|
||||
import { connectIrcClient } from "./client.js";
|
||||
import { buildIrcConnectOptions } from "./connect-options.js";
|
||||
@ -67,13 +68,19 @@ export async function sendMessageIrc(
|
||||
if (client?.isReady()) {
|
||||
client.sendPrivmsg(target, payload);
|
||||
} else {
|
||||
const transient = await connectIrcClient(
|
||||
buildIrcConnectOptions(account, {
|
||||
connectTimeoutMs: 12000,
|
||||
}),
|
||||
);
|
||||
transient.sendPrivmsg(target, payload);
|
||||
transient.quit("sent");
|
||||
// Try the monitor's persistent client first (already connected and joined to channels)
|
||||
const active = getActiveClient(account.accountId);
|
||||
if (active) {
|
||||
active.sendPrivmsg(target, payload);
|
||||
} else {
|
||||
const transient = await connectIrcClient(
|
||||
buildIrcConnectOptions(account, {
|
||||
connectTimeoutMs: 12000,
|
||||
}),
|
||||
);
|
||||
transient.sendPrivmsg(target, payload);
|
||||
transient.quit("sent");
|
||||
}
|
||||
}
|
||||
|
||||
runtime.channel.activity.record({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user