mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:50:43 +00:00
fix(config): coerce visible replies booleans
This commit is contained in:
@@ -29,6 +29,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Config/messages: coerce boolean `messages.visibleReplies` and `messages.groupChat.visibleReplies` values to the documented enum modes so an intuitive toggle no longer invalidates config and drops channel startup. Fixes #75390. Thanks @scottgl9.
|
||||
- Feishu: accept and honor `channels.feishu.blockStreaming` at the top level and per account, while keeping the legacy default off so Feishu cards no longer reject documented config or silently drop block replies. Fixes #75555. Thanks @vincentkoc.
|
||||
- Google Chat: normalize custom Google auth transport headers before google-auth/gaxios interceptors run, restoring webhook token verification when certificate retrieval expects Fetch `Headers`. Fixes #76742. Thanks @donbowman.
|
||||
- Doctor/plugins: reset stale `plugins.slots.memory` and `plugins.slots.contextEngine` references during `doctor --fix`, so cleanup of missing plugin config does not leave unrecoverable slot owners behind. Fixes #76550 and #76551. Thanks @vincentkoc.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
d9dbaace82aff4445be6ed11e52e69b4548239e3a4e659538f96dfb3ed3c57ac config-baseline.json
|
||||
9d4d4ab553dadca237d837f71dc7fc13e4ea65d33a564c2ea6775180c413e86a config-baseline.core.json
|
||||
f2a1aad257c570b497865680c331568a6775369528749826dfa35c1f644483fc config-baseline.channel.json
|
||||
858f82733d9828b28bf88bc226e155d8417c494215eb3f808f15799daa42a7d7 config-baseline.plugin.json
|
||||
c1de046645b03b1ec47ec41811b67c0e7ad5460842b54416a47757ef22b9b17e config-baseline.json
|
||||
f945a060012b3e7c675fb3ea0c5f18996cdcc06c9ec6cead389e04791a529ce9 config-baseline.core.json
|
||||
76979aba007500abc52b970da76b6512291916739c29d6a3f4218772d1a31186 config-baseline.channel.json
|
||||
245aa98aabc6c2e3c57a69e639c2fb10d84a7e1e1b3bcdadc340fa61ca998287 config-baseline.plugin.json
|
||||
|
||||
@@ -7388,8 +7388,15 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
||||
maximum: 9007199254740991,
|
||||
},
|
||||
visibleReplies: {
|
||||
type: "string",
|
||||
enum: ["automatic", "message_tool"],
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
enum: ["automatic", "message_tool"],
|
||||
},
|
||||
{
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
@@ -19019,8 +19026,15 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
||||
"Prefix text prepended to inbound user messages before they are handed to the agent runtime. Use this sparingly for channel context markers and keep it stable across sessions.",
|
||||
},
|
||||
visibleReplies: {
|
||||
type: "string",
|
||||
enum: ["automatic", "message_tool"],
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
enum: ["automatic", "message_tool"],
|
||||
},
|
||||
{
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
title: "Visible Replies",
|
||||
description:
|
||||
'Controls visible source replies across direct, group, and channel conversations. "message_tool" keeps normal final replies private and requires message(action=send) for visible output; "automatic" posts normal replies as before.',
|
||||
@@ -19052,8 +19066,15 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
||||
"Maximum number of prior group messages loaded as context per turn for group sessions. Use higher values for richer continuity, or lower values for faster and cheaper responses.",
|
||||
},
|
||||
visibleReplies: {
|
||||
type: "string",
|
||||
enum: ["automatic", "message_tool"],
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
enum: ["automatic", "message_tool"],
|
||||
},
|
||||
{
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
title: "Group Visible Replies",
|
||||
description:
|
||||
'Overrides visible source replies for group/channel conversations. Defaults to "message_tool" when no global visible reply policy is set. "message_tool" keeps normal final replies private and requires message(action=send) for room output; "automatic" posts normal replies as before.',
|
||||
|
||||
@@ -386,11 +386,25 @@ export const ModelsConfigSchema = z
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
const VisibleRepliesValueSchema = z.enum(["automatic", "message_tool"]);
|
||||
|
||||
export const VisibleRepliesSchema = z
|
||||
.union([VisibleRepliesValueSchema, z.boolean()])
|
||||
.overwrite((value) => {
|
||||
if (value === true) {
|
||||
return "automatic";
|
||||
}
|
||||
if (value === false) {
|
||||
return "message_tool";
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
export const GroupChatSchema = z
|
||||
.object({
|
||||
mentionPatterns: z.array(z.string()).optional(),
|
||||
historyLimit: z.number().int().positive().optional(),
|
||||
visibleReplies: z.enum(["automatic", "message_tool"]).optional(),
|
||||
visibleReplies: VisibleRepliesSchema.optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
QueueSchema,
|
||||
TypingModeSchema,
|
||||
TtsConfigSchema,
|
||||
VisibleRepliesSchema,
|
||||
} from "./zod-schema.core.js";
|
||||
import { sensitive } from "./zod-schema.sensitive.js";
|
||||
|
||||
@@ -152,7 +153,7 @@ export const SessionSchema = z
|
||||
export const MessagesSchema = z
|
||||
.object({
|
||||
messagePrefix: z.string().optional(),
|
||||
visibleReplies: z.enum(["automatic", "message_tool"]).optional(),
|
||||
visibleReplies: VisibleRepliesSchema.optional(),
|
||||
responsePrefix: z.string().optional(),
|
||||
groupChat: GroupChatSchema,
|
||||
queue: QueueSchema,
|
||||
|
||||
69
src/config/zod-schema.visible-replies.test.ts
Normal file
69
src/config/zod-schema.visible-replies.test.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { validateConfigObjectRaw } from "./validation.js";
|
||||
|
||||
describe("visible reply config schema", () => {
|
||||
it("coerces boolean global visibleReplies values to the enum contract", () => {
|
||||
const automatic = validateConfigObjectRaw({
|
||||
messages: {
|
||||
visibleReplies: true,
|
||||
},
|
||||
});
|
||||
const toolOnly = validateConfigObjectRaw({
|
||||
messages: {
|
||||
visibleReplies: false,
|
||||
},
|
||||
});
|
||||
|
||||
expect(automatic.ok).toBe(true);
|
||||
expect(toolOnly.ok).toBe(true);
|
||||
if (automatic.ok) {
|
||||
expect(automatic.config.messages?.visibleReplies).toBe("automatic");
|
||||
}
|
||||
if (toolOnly.ok) {
|
||||
expect(toolOnly.config.messages?.visibleReplies).toBe("message_tool");
|
||||
}
|
||||
});
|
||||
|
||||
it("coerces boolean groupChat visibleReplies values to the enum contract", () => {
|
||||
const automatic = validateConfigObjectRaw({
|
||||
messages: {
|
||||
groupChat: {
|
||||
visibleReplies: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
const toolOnly = validateConfigObjectRaw({
|
||||
messages: {
|
||||
groupChat: {
|
||||
visibleReplies: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(automatic.ok).toBe(true);
|
||||
expect(toolOnly.ok).toBe(true);
|
||||
if (automatic.ok) {
|
||||
expect(automatic.config.messages?.groupChat?.visibleReplies).toBe("automatic");
|
||||
}
|
||||
if (toolOnly.ok) {
|
||||
expect(toolOnly.config.messages?.groupChat?.visibleReplies).toBe("message_tool");
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps invalid visibleReplies values rejected", () => {
|
||||
const result = validateConfigObjectRaw({
|
||||
messages: {
|
||||
visibleReplies: "visible",
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.issues).toContainEqual(
|
||||
expect.objectContaining({
|
||||
path: "messages.visibleReplies",
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user