Files
openclaw/src/plugins/runtime/runtime-discord-typing.ts
T
Harold Hunt aa1454d1a8 Plugins: broaden plugin surface for Codex App Server (#45318)
* Plugins: add inbound claim and Telegram interaction seams

* Plugins: add Discord interaction surface

* Chore: fix formatting after plugin rebase

* fix(hooks): preserve observers after inbound claim

* test(hooks): cover claimed inbound observer delivery

* fix(plugins): harden typing lease refreshes

* fix(discord): pass real auth to plugin interactions

* fix(plugins): remove raw session binding runtime exposure

* fix(plugins): tighten interactive callback handling

* Plugins: gate conversation binding with approvals

* Plugins: migrate legacy plugin binding records

* Plugins/phone-control: update test command context

* Plugins: migrate legacy binding ids

* Plugins: migrate legacy codex session bindings

* Discord: fix plugin interaction handling

* Discord: support direct plugin conversation binds

* Plugins: preserve Discord command bind targets

* Tests: fix plugin binding and interactive fallout

* Discord: stabilize directory lookup tests

* Discord: route bound DMs to plugins

* Discord: restore plugin bindings after restart

* Telegram: persist detached plugin bindings

* Plugins: limit binding APIs to Telegram and Discord

* Plugins: harden bound conversation routing

* Plugins: fix extension target imports

* Plugins: fix Telegram runtime extension imports

* Plugins: format rebased binding handlers

* Discord: bind group DM interactions by channel

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-15 16:06:11 -07:00

63 lines
1.5 KiB
TypeScript

import { logWarn } from "../../logger.js";
export type CreateDiscordTypingLeaseParams = {
channelId: string;
accountId?: string;
cfg?: ReturnType<typeof import("../../config/config.js").loadConfig>;
intervalMs?: number;
pulse: (params: {
channelId: string;
accountId?: string;
cfg?: ReturnType<typeof import("../../config/config.js").loadConfig>;
}) => Promise<void>;
};
const DEFAULT_DISCORD_TYPING_INTERVAL_MS = 8_000;
export async function createDiscordTypingLease(params: CreateDiscordTypingLeaseParams): Promise<{
refresh: () => Promise<void>;
stop: () => void;
}> {
const intervalMs =
typeof params.intervalMs === "number" && Number.isFinite(params.intervalMs)
? Math.max(1_000, Math.floor(params.intervalMs))
: DEFAULT_DISCORD_TYPING_INTERVAL_MS;
let stopped = false;
let timer: ReturnType<typeof setInterval> | null = null;
const pulse = async () => {
if (stopped) {
return;
}
await params.pulse({
channelId: params.channelId,
accountId: params.accountId,
cfg: params.cfg,
});
};
await pulse();
timer = setInterval(() => {
// Background lease refreshes must never escape as unhandled rejections.
void pulse().catch((err) => {
logWarn(`plugins: discord typing pulse failed: ${String(err)}`);
});
}, intervalMs);
timer.unref?.();
return {
refresh: async () => {
await pulse();
},
stop: () => {
stopped = true;
if (timer) {
clearInterval(timer);
timer = null;
}
},
};
}