feat(queue): add per-channel debounce overrides
This commit is contained in:
@@ -11,6 +11,7 @@ Docs: https://docs.clawd.bot
|
||||
- Nodes: expose node PATH in status/describe and bootstrap PATH for node-host execution.
|
||||
- CLI: flatten node service commands under `clawdbot node` and remove `service node` docs.
|
||||
- CLI: move gateway service commands under `clawdbot gateway` and add `gateway probe` for reachability.
|
||||
- Queue: allow per-channel debounce overrides and plugin defaults. (#1190) Thanks @cheeeee.
|
||||
|
||||
### Fixes
|
||||
- Embedded runner: persist injected history images so attachments aren’t reloaded each turn. (#1374) Thanks @Nicell.
|
||||
|
||||
@@ -11,8 +11,7 @@ const resolveChannelOverride = (params: {
|
||||
channel: string;
|
||||
}): number | undefined => {
|
||||
if (!params.byChannel) return undefined;
|
||||
const channelKey = params.channel as keyof InboundDebounceByProvider;
|
||||
return resolveMs(params.byChannel[channelKey]);
|
||||
return resolveMs(params.byChannel[params.channel]);
|
||||
};
|
||||
|
||||
export function resolveInboundDebounceMs(params: {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { getChannelPlugin } from "../../../channels/plugins/index.js";
|
||||
import type { InboundDebounceByProvider } from "../../../config/types.messages.js";
|
||||
import { normalizeQueueDropPolicy, normalizeQueueMode } from "./normalize.js";
|
||||
import { DEFAULT_QUEUE_CAP, DEFAULT_QUEUE_DEBOUNCE_MS, DEFAULT_QUEUE_DROP } from "./state.js";
|
||||
import type { QueueMode, QueueSettings, ResolveQueueSettingsParams } from "./types.js";
|
||||
@@ -6,6 +8,23 @@ function defaultQueueModeForChannel(_channel?: string): QueueMode {
|
||||
return "collect";
|
||||
}
|
||||
|
||||
/** Resolve per-channel debounce override from debounceMsByChannel map. */
|
||||
function resolveChannelDebounce(
|
||||
byChannel: InboundDebounceByProvider | undefined,
|
||||
channelKey: string | undefined,
|
||||
): number | undefined {
|
||||
if (!channelKey || !byChannel) return undefined;
|
||||
const value = byChannel[channelKey];
|
||||
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : undefined;
|
||||
}
|
||||
|
||||
function resolvePluginDebounce(channelKey: string | undefined): number | undefined {
|
||||
if (!channelKey) return undefined;
|
||||
const plugin = getChannelPlugin(channelKey);
|
||||
const value = plugin?.defaults?.queue?.debounceMs;
|
||||
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : undefined;
|
||||
}
|
||||
|
||||
export function resolveQueueSettings(params: ResolveQueueSettingsParams): QueueSettings {
|
||||
const channelKey = params.channel?.trim().toLowerCase();
|
||||
const queueCfg = params.cfg.messages?.queue;
|
||||
@@ -22,6 +41,8 @@ export function resolveQueueSettings(params: ResolveQueueSettingsParams): QueueS
|
||||
const debounceRaw =
|
||||
params.inlineOptions?.debounceMs ??
|
||||
params.sessionEntry?.queueDebounceMs ??
|
||||
resolveChannelDebounce(queueCfg?.debounceMsByChannel, channelKey) ??
|
||||
resolvePluginDebounce(channelKey) ??
|
||||
queueCfg?.debounceMs ??
|
||||
DEFAULT_QUEUE_DEBOUNCE_MS;
|
||||
const capRaw =
|
||||
|
||||
@@ -48,6 +48,11 @@ export type ChannelPlugin<ResolvedAccount = any> = {
|
||||
id: ChannelId;
|
||||
meta: ChannelMeta;
|
||||
capabilities: ChannelCapabilities;
|
||||
defaults?: {
|
||||
queue?: {
|
||||
debounceMs?: number;
|
||||
};
|
||||
};
|
||||
reload?: { configPrefixes: string[]; noopPrefixes?: string[] };
|
||||
// CLI onboarding wizard hooks for this channel.
|
||||
onboarding?: ChannelOnboardingAdapter;
|
||||
|
||||
@@ -13,20 +13,13 @@ export type QueueConfig = {
|
||||
mode?: QueueMode;
|
||||
byChannel?: QueueModeByProvider;
|
||||
debounceMs?: number;
|
||||
/** Per-channel debounce overrides (ms). */
|
||||
debounceMsByChannel?: InboundDebounceByProvider;
|
||||
cap?: number;
|
||||
drop?: QueueDropPolicy;
|
||||
};
|
||||
|
||||
export type InboundDebounceByProvider = {
|
||||
whatsapp?: number;
|
||||
telegram?: number;
|
||||
discord?: number;
|
||||
slack?: number;
|
||||
signal?: number;
|
||||
imessage?: number;
|
||||
msteams?: number;
|
||||
webchat?: number;
|
||||
};
|
||||
export type InboundDebounceByProvider = Record<string, number>;
|
||||
|
||||
export type InboundDebounceConfig = {
|
||||
debounceMs?: number;
|
||||
|
||||
@@ -217,17 +217,7 @@ export const QueueModeBySurfaceSchema = z
|
||||
.optional();
|
||||
|
||||
export const DebounceMsBySurfaceSchema = z
|
||||
.object({
|
||||
whatsapp: z.number().int().nonnegative().optional(),
|
||||
telegram: z.number().int().nonnegative().optional(),
|
||||
discord: z.number().int().nonnegative().optional(),
|
||||
slack: z.number().int().nonnegative().optional(),
|
||||
signal: z.number().int().nonnegative().optional(),
|
||||
imessage: z.number().int().nonnegative().optional(),
|
||||
msteams: z.number().int().nonnegative().optional(),
|
||||
webchat: z.number().int().nonnegative().optional(),
|
||||
})
|
||||
.strict()
|
||||
.record(z.string(), z.number().int().nonnegative())
|
||||
.optional();
|
||||
|
||||
export const QueueSchema = z
|
||||
@@ -235,6 +225,7 @@ export const QueueSchema = z
|
||||
mode: QueueModeSchema.optional(),
|
||||
byChannel: QueueModeBySurfaceSchema,
|
||||
debounceMs: z.number().int().nonnegative().optional(),
|
||||
debounceMsByChannel: DebounceMsBySurfaceSchema,
|
||||
cap: z.number().int().positive().optional(),
|
||||
drop: QueueDropSchema.optional(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user