Config: add support for per-provider blockStreaming override

This commit is contained in:
Jake
2026-01-09 11:57:43 +13:00
committed by Peter Steinberger
parent 91a6f721a3
commit a05916bee8
10 changed files with 68 additions and 5 deletions

View File

@@ -440,7 +440,13 @@ export async function getReplyFromConfig(
"on") "on")
: "off"; : "off";
const resolvedBlockStreaming = const resolvedBlockStreaming =
agentCfg?.blockStreamingDefault === "off" ? "off" : "on"; opts?.disableBlockStreaming === true
? "off"
: opts?.disableBlockStreaming === false
? "on"
: agentCfg?.blockStreamingDefault === "off"
? "off"
: "on";
const resolvedBlockStreamingBreak: "text_end" | "message_end" = const resolvedBlockStreamingBreak: "text_end" | "message_end" =
agentCfg?.blockStreamingBreak === "message_end" agentCfg?.blockStreamingBreak === "message_end"
? "message_end" ? "message_end"

View File

@@ -125,6 +125,8 @@ export type WhatsAppConfig = {
groupPolicy?: GroupPolicy; groupPolicy?: GroupPolicy;
/** Outbound text chunk size (chars). Default: 4000. */ /** Outbound text chunk size (chars). Default: 4000. */
textChunkLimit?: number; textChunkLimit?: number;
/** Disable block streaming for this account. */
blockStreaming?: boolean;
/** Per-action tool gating (default: true for all). */ /** Per-action tool gating (default: true for all). */
actions?: WhatsAppActionConfig; actions?: WhatsAppActionConfig;
groups?: Record< groups?: Record<
@@ -150,6 +152,7 @@ export type WhatsAppAccountConfig = {
groupAllowFrom?: string[]; groupAllowFrom?: string[];
groupPolicy?: GroupPolicy; groupPolicy?: GroupPolicy;
textChunkLimit?: number; textChunkLimit?: number;
blockStreaming?: boolean;
groups?: Record< groups?: Record<
string, string,
{ {
@@ -301,6 +304,8 @@ export type TelegramAccountConfig = {
groupPolicy?: GroupPolicy; groupPolicy?: GroupPolicy;
/** Outbound text chunk size (chars). Default: 4000. */ /** Outbound text chunk size (chars). Default: 4000. */
textChunkLimit?: number; textChunkLimit?: number;
/** Disable block streaming for this account. */
blockStreaming?: boolean;
/** Draft streaming mode for Telegram (off|partial|block). Default: partial. */ /** Draft streaming mode for Telegram (off|partial|block). Default: partial. */
streamMode?: "off" | "partial" | "block"; streamMode?: "off" | "partial" | "block";
mediaMaxMb?: number; mediaMaxMb?: number;
@@ -422,6 +427,8 @@ export type DiscordAccountConfig = {
groupPolicy?: GroupPolicy; groupPolicy?: GroupPolicy;
/** Outbound text chunk size (chars). Default: 2000. */ /** Outbound text chunk size (chars). Default: 2000. */
textChunkLimit?: number; textChunkLimit?: number;
/** Disable block streaming for this account. */
blockStreaming?: boolean;
/** /**
* Soft max line count per Discord message. * Soft max line count per Discord message.
* Discord clients can clip/collapse very tall messages; splitting by lines * Discord clients can clip/collapse very tall messages; splitting by lines
@@ -517,6 +524,7 @@ export type SlackAccountConfig = {
*/ */
groupPolicy?: GroupPolicy; groupPolicy?: GroupPolicy;
textChunkLimit?: number; textChunkLimit?: number;
blockStreaming?: boolean;
mediaMaxMb?: number; mediaMaxMb?: number;
/** Reaction notification mode (off|own|all|allowlist). Default: own. */ /** Reaction notification mode (off|own|all|allowlist). Default: own. */
reactionNotifications?: SlackReactionNotificationMode; reactionNotifications?: SlackReactionNotificationMode;
@@ -570,6 +578,7 @@ export type SignalAccountConfig = {
groupPolicy?: GroupPolicy; groupPolicy?: GroupPolicy;
/** Outbound text chunk size (chars). Default: 4000. */ /** Outbound text chunk size (chars). Default: 4000. */
textChunkLimit?: number; textChunkLimit?: number;
blockStreaming?: boolean;
mediaMaxMb?: number; mediaMaxMb?: number;
}; };
@@ -668,6 +677,7 @@ export type IMessageAccountConfig = {
mediaMaxMb?: number; mediaMaxMb?: number;
/** Outbound text chunk size (chars). Default: 4000. */ /** Outbound text chunk size (chars). Default: 4000. */
textChunkLimit?: number; textChunkLimit?: number;
blockStreaming?: boolean;
groups?: Record< groups?: Record<
string, string,
{ {

View File

@@ -191,6 +191,7 @@ const TelegramAccountSchemaBase = z.object({
groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(), groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupPolicy: GroupPolicySchema.optional().default("open"), groupPolicy: GroupPolicySchema.optional().default("open"),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(),
streamMode: z.enum(["off", "partial", "block"]).optional().default("partial"), streamMode: z.enum(["off", "partial", "block"]).optional().default("partial"),
mediaMaxMb: z.number().positive().optional(), mediaMaxMb: z.number().positive().optional(),
retry: RetryConfigSchema, retry: RetryConfigSchema,
@@ -275,6 +276,7 @@ const DiscordAccountSchema = z.object({
token: z.string().optional(), token: z.string().optional(),
groupPolicy: GroupPolicySchema.optional().default("open"), groupPolicy: GroupPolicySchema.optional().default("open"),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(),
maxLinesPerMessage: z.number().int().positive().optional(), maxLinesPerMessage: z.number().int().positive().optional(),
mediaMaxMb: z.number().positive().optional(), mediaMaxMb: z.number().positive().optional(),
historyLimit: z.number().int().min(0).optional(), historyLimit: z.number().int().min(0).optional(),
@@ -344,6 +346,7 @@ const SlackAccountSchema = z.object({
allowBots: z.boolean().optional(), allowBots: z.boolean().optional(),
groupPolicy: GroupPolicySchema.optional().default("open"), groupPolicy: GroupPolicySchema.optional().default("open"),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(),
mediaMaxMb: z.number().positive().optional(), mediaMaxMb: z.number().positive().optional(),
reactionNotifications: z.enum(["off", "own", "all", "allowlist"]).optional(), reactionNotifications: z.enum(["off", "own", "all", "allowlist"]).optional(),
reactionAllowlist: z.array(z.union([z.string(), z.number()])).optional(), reactionAllowlist: z.array(z.union([z.string(), z.number()])).optional(),
@@ -394,6 +397,7 @@ const SignalAccountSchemaBase = z.object({
groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(), groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupPolicy: GroupPolicySchema.optional().default("open"), groupPolicy: GroupPolicySchema.optional().default("open"),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(),
mediaMaxMb: z.number().int().positive().optional(), mediaMaxMb: z.number().int().positive().optional(),
}); });
@@ -438,6 +442,7 @@ const IMessageAccountSchemaBase = z.object({
includeAttachments: z.boolean().optional(), includeAttachments: z.boolean().optional(),
mediaMaxMb: z.number().int().positive().optional(), mediaMaxMb: z.number().int().positive().optional(),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(),
groups: z groups: z
.record( .record(
z.string(), z.string(),
@@ -1209,6 +1214,7 @@ export const ClawdbotSchema = z.object({
groupAllowFrom: z.array(z.string()).optional(), groupAllowFrom: z.array(z.string()).optional(),
groupPolicy: GroupPolicySchema.optional().default("open"), groupPolicy: GroupPolicySchema.optional().default("open"),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(),
groups: z groups: z
.record( .record(
z.string(), z.string(),
@@ -1242,6 +1248,7 @@ export const ClawdbotSchema = z.object({
groupAllowFrom: z.array(z.string()).optional(), groupAllowFrom: z.array(z.string()).optional(),
groupPolicy: GroupPolicySchema.optional().default("open"), groupPolicy: GroupPolicySchema.optional().default("open"),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(),
actions: z actions: z
.object({ .object({
reactions: z.boolean().optional(), reactions: z.boolean().optional(),

View File

@@ -1150,7 +1150,14 @@ export function createDiscordMessageHandler(params: {
ctx: ctxPayload, ctx: ctxPayload,
cfg, cfg,
dispatcher, dispatcher,
replyOptions: { ...replyOptions, skillFilter: channelConfig?.skills }, replyOptions: {
...replyOptions,
skillFilter: channelConfig?.skills,
disableBlockStreaming:
typeof discordConfig?.blockStreaming === "boolean"
? !discordConfig.blockStreaming
: undefined,
},
}); });
markDispatchIdle(); markDispatchIdle();
if (!queuedFinal) { if (!queuedFinal) {

View File

@@ -466,6 +466,12 @@ export async function monitorIMessageProvider(
ctx: ctxPayload, ctx: ctxPayload,
cfg, cfg,
dispatcher, dispatcher,
replyOptions: {
disableBlockStreaming:
typeof accountInfo.config.blockStreaming === "boolean"
? !accountInfo.config.blockStreaming
: undefined,
},
}); });
if (!queuedFinal) return; if (!queuedFinal) return;
}; };

View File

@@ -533,6 +533,12 @@ export async function monitorSignalProvider(
ctx: ctxPayload, ctx: ctxPayload,
cfg, cfg,
dispatcher, dispatcher,
replyOptions: {
disableBlockStreaming:
typeof accountInfo.config.blockStreaming === "boolean"
? !accountInfo.config.blockStreaming
: undefined,
},
}); });
if (!queuedFinal) return; if (!queuedFinal) return;
}; };

View File

@@ -1116,7 +1116,14 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
ctx: ctxPayload, ctx: ctxPayload,
cfg, cfg,
dispatcher, dispatcher,
replyOptions: { ...replyOptions, skillFilter: channelConfig?.skills }, replyOptions: {
...replyOptions,
skillFilter: channelConfig?.skills,
disableBlockStreaming:
typeof account.config.blockStreaming === "boolean"
? !account.config.blockStreaming
: undefined,
},
}); });
markDispatchIdle(); markDispatchIdle();
if (didSetStatus) { if (didSetStatus) {

View File

@@ -770,7 +770,11 @@ export function createTelegramBot(opts: TelegramBotOptions) {
if (payload.text) draftStream.update(payload.text); if (payload.text) draftStream.update(payload.text);
} }
: undefined, : undefined,
disableBlockStreaming: Boolean(draftStream), disableBlockStreaming:
Boolean(draftStream) ||
(typeof telegramCfg.blockStreaming === "boolean"
? !telegramCfg.blockStreaming
: undefined),
}, },
}); });
markDispatchIdle(); markDispatchIdle();

View File

@@ -23,6 +23,7 @@ export type ResolvedWhatsAppAccount = {
groupPolicy?: GroupPolicy; groupPolicy?: GroupPolicy;
dmPolicy?: DmPolicy; dmPolicy?: DmPolicy;
textChunkLimit?: number; textChunkLimit?: number;
blockStreaming?: boolean;
groups?: WhatsAppAccountConfig["groups"]; groups?: WhatsAppAccountConfig["groups"];
}; };
@@ -119,6 +120,8 @@ export function resolveWhatsAppAccount(params: {
groupPolicy: accountCfg?.groupPolicy ?? params.cfg.whatsapp?.groupPolicy, groupPolicy: accountCfg?.groupPolicy ?? params.cfg.whatsapp?.groupPolicy,
textChunkLimit: textChunkLimit:
accountCfg?.textChunkLimit ?? params.cfg.whatsapp?.textChunkLimit, accountCfg?.textChunkLimit ?? params.cfg.whatsapp?.textChunkLimit,
blockStreaming:
accountCfg?.blockStreaming ?? params.cfg.whatsapp?.blockStreaming,
groups: accountCfg?.groups ?? params.cfg.whatsapp?.groups, groups: accountCfg?.groups ?? params.cfg.whatsapp?.groups,
}; };
} }

View File

@@ -788,6 +788,7 @@ export async function monitorWebProvider(
groupAllowFrom: account.groupAllowFrom, groupAllowFrom: account.groupAllowFrom,
groupPolicy: account.groupPolicy, groupPolicy: account.groupPolicy,
textChunkLimit: account.textChunkLimit, textChunkLimit: account.textChunkLimit,
blockStreaming: account.blockStreaming,
groups: account.groups, groups: account.groups,
}, },
} satisfies ReturnType<typeof loadConfig>; } satisfies ReturnType<typeof loadConfig>;
@@ -1276,7 +1277,13 @@ export async function monitorWebProvider(
cfg, cfg,
dispatcher, dispatcher,
replyResolver, replyResolver,
replyOptions, replyOptions: {
...replyOptions,
disableBlockStreaming:
typeof cfg.whatsapp?.blockStreaming === "boolean"
? !cfg.whatsapp.blockStreaming
: undefined,
},
}); });
markDispatchIdle(); markDispatchIdle();
if (!queuedFinal) { if (!queuedFinal) {