@@ -7,6 +7,7 @@
|
|||||||
- Memory: allow custom OpenAI-compatible embedding endpoints for memory search (remote baseUrl/apiKey/headers). (#819 — thanks @mukhtharcm)
|
- Memory: allow custom OpenAI-compatible embedding endpoints for memory search (remote baseUrl/apiKey/headers). (#819 — thanks @mukhtharcm)
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
- Discord: avoid duplicate message/reaction listeners on monitor reloads. (#744 — thanks @thewilloftheshadow)
|
||||||
- System events: include local timestamps when events are injected into prompts. (#245 — thanks @thewilloftheshadow)
|
- System events: include local timestamps when events are injected into prompts. (#245 — thanks @thewilloftheshadow)
|
||||||
- Cron: accept `jobId` aliases for cron update/run/remove params in gateway validation. (#252 — thanks @thewilloftheshadow)
|
- Cron: accept `jobId` aliases for cron update/run/remove params in gateway validation. (#252 — thanks @thewilloftheshadow)
|
||||||
- Models/Google: normalize Gemini 3 model ids to preview variants before runtime selection. (#795 — thanks @thewilloftheshadow)
|
- Models/Google: normalize Gemini 3 model ids to preview variants before runtime selection. (#795 — thanks @thewilloftheshadow)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
isDiscordGroupAllowedByPolicy,
|
isDiscordGroupAllowedByPolicy,
|
||||||
normalizeDiscordAllowList,
|
normalizeDiscordAllowList,
|
||||||
normalizeDiscordSlug,
|
normalizeDiscordSlug,
|
||||||
|
registerDiscordListener,
|
||||||
resolveDiscordChannelConfig,
|
resolveDiscordChannelConfig,
|
||||||
resolveDiscordGuildEntry,
|
resolveDiscordGuildEntry,
|
||||||
resolveDiscordReplyTarget,
|
resolveDiscordReplyTarget,
|
||||||
@@ -34,6 +35,18 @@ const makeEntries = (
|
|||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
describe("registerDiscordListener", () => {
|
||||||
|
class FakeListener {}
|
||||||
|
|
||||||
|
it("dedupes listeners by constructor", () => {
|
||||||
|
const listeners: object[] = [];
|
||||||
|
|
||||||
|
expect(registerDiscordListener(listeners, new FakeListener())).toBe(true);
|
||||||
|
expect(registerDiscordListener(listeners, new FakeListener())).toBe(false);
|
||||||
|
expect(listeners).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("discord allowlist helpers", () => {
|
describe("discord allowlist helpers", () => {
|
||||||
it("normalizes slugs", () => {
|
it("normalizes slugs", () => {
|
||||||
expect(normalizeDiscordSlug("Friends of Clawd")).toBe("friends-of-clawd");
|
expect(normalizeDiscordSlug("Friends of Clawd")).toBe("friends-of-clawd");
|
||||||
|
|||||||
@@ -175,6 +175,17 @@ function logSlowDiscordListener(params: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function registerDiscordListener(
|
||||||
|
listeners: Array<object>,
|
||||||
|
listener: object,
|
||||||
|
) {
|
||||||
|
if (listeners.some((existing) => existing.constructor === listener.constructor)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
listeners.push(listener);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
async function resolveDiscordThreadStarter(params: {
|
async function resolveDiscordThreadStarter(params: {
|
||||||
channel: DiscordThreadChannel;
|
channel: DiscordThreadChannel;
|
||||||
client: Client;
|
client: Client;
|
||||||
@@ -602,8 +613,12 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
|
|||||||
guildEntries,
|
guildEntries,
|
||||||
});
|
});
|
||||||
|
|
||||||
client.listeners.push(new DiscordMessageListener(messageHandler, logger));
|
registerDiscordListener(
|
||||||
client.listeners.push(
|
client.listeners,
|
||||||
|
new DiscordMessageListener(messageHandler, logger),
|
||||||
|
);
|
||||||
|
registerDiscordListener(
|
||||||
|
client.listeners,
|
||||||
new DiscordReactionListener({
|
new DiscordReactionListener({
|
||||||
cfg,
|
cfg,
|
||||||
accountId: account.accountId,
|
accountId: account.accountId,
|
||||||
@@ -613,7 +628,8 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
|
|||||||
logger,
|
logger,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
client.listeners.push(
|
registerDiscordListener(
|
||||||
|
client.listeners,
|
||||||
new DiscordReactionRemoveListener({
|
new DiscordReactionRemoveListener({
|
||||||
cfg,
|
cfg,
|
||||||
accountId: account.accountId,
|
accountId: account.accountId,
|
||||||
|
|||||||
Reference in New Issue
Block a user