feat: add ack reaction defaults
This commit is contained in:
@@ -87,6 +87,57 @@ describe("config identity defaults", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("defaults ackReaction to identity emoji", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
identity: { name: "Samantha", theme: "helpful sloth", emoji: "🦥" },
|
||||
messages: {},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
vi.resetModules();
|
||||
const { loadConfig } = await import("./config.js");
|
||||
const cfg = loadConfig();
|
||||
|
||||
expect(cfg.messages?.ackReaction).toBe("🦥");
|
||||
expect(cfg.messages?.ackReactionScope).toBe("group-mentions");
|
||||
});
|
||||
});
|
||||
|
||||
it("defaults ackReaction to 👀 when identity is missing", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
messages: {},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
vi.resetModules();
|
||||
const { loadConfig } = await import("./config.js");
|
||||
const cfg = loadConfig();
|
||||
|
||||
expect(cfg.messages?.ackReaction).toBe("👀");
|
||||
expect(cfg.messages?.ackReactionScope).toBe("group-mentions");
|
||||
});
|
||||
});
|
||||
|
||||
it("does not override explicit values", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
|
||||
@@ -54,6 +54,32 @@ export function applyIdentityDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
return mutated ? next : cfg;
|
||||
}
|
||||
|
||||
export function applyMessageDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
const messages = cfg.messages;
|
||||
const hasAckReaction = messages?.ackReaction !== undefined;
|
||||
const hasAckScope = messages?.ackReactionScope !== undefined;
|
||||
if (hasAckReaction && hasAckScope) return cfg;
|
||||
|
||||
const fallbackEmoji = cfg.identity?.emoji?.trim() || "👀";
|
||||
const nextMessages = { ...(messages ?? {}) };
|
||||
let mutated = false;
|
||||
|
||||
if (!hasAckReaction) {
|
||||
nextMessages.ackReaction = fallbackEmoji;
|
||||
mutated = true;
|
||||
}
|
||||
if (!hasAckScope) {
|
||||
nextMessages.ackReactionScope = "group-mentions";
|
||||
mutated = true;
|
||||
}
|
||||
|
||||
if (!mutated) return cfg;
|
||||
return {
|
||||
...cfg,
|
||||
messages: nextMessages,
|
||||
};
|
||||
}
|
||||
|
||||
export function applySessionDefaults(
|
||||
cfg: ClawdbotConfig,
|
||||
options: SessionDefaultsOptions = {},
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import {
|
||||
applyIdentityDefaults,
|
||||
applyLoggingDefaults,
|
||||
applyMessageDefaults,
|
||||
applyModelDefaults,
|
||||
applySessionDefaults,
|
||||
applyTalkApiKey,
|
||||
@@ -117,7 +118,9 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
const cfg = applyModelDefaults(
|
||||
applySessionDefaults(
|
||||
applyLoggingDefaults(
|
||||
applyIdentityDefaults(validated.data as ClawdbotConfig),
|
||||
applyMessageDefaults(
|
||||
applyIdentityDefaults(validated.data as ClawdbotConfig),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -148,7 +151,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
const exists = deps.fs.existsSync(configPath);
|
||||
if (!exists) {
|
||||
const config = applyTalkApiKey(
|
||||
applyModelDefaults(applySessionDefaults({})),
|
||||
applyModelDefaults(applySessionDefaults(applyMessageDefaults({}))),
|
||||
);
|
||||
const legacyIssues: LegacyConfigIssue[] = [];
|
||||
return {
|
||||
@@ -205,7 +208,9 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
valid: true,
|
||||
config: applyTalkApiKey(
|
||||
applyModelDefaults(
|
||||
applySessionDefaults(applyLoggingDefaults(validated.config)),
|
||||
applySessionDefaults(
|
||||
applyLoggingDefaults(applyMessageDefaults(validated.config)),
|
||||
),
|
||||
),
|
||||
),
|
||||
issues: [],
|
||||
|
||||
@@ -97,6 +97,8 @@ const FIELD_LABELS: Record<string, string> = {
|
||||
"ui.seamColor": "Accent Color",
|
||||
"browser.controlUrl": "Browser Control URL",
|
||||
"session.agentToAgent.maxPingPongTurns": "Agent-to-Agent Ping-Pong Turns",
|
||||
"messages.ackReaction": "Ack Reaction Emoji",
|
||||
"messages.ackReactionScope": "Ack Reaction Scope",
|
||||
"talk.apiKey": "Talk API Key",
|
||||
"telegram.botToken": "Telegram Bot Token",
|
||||
"discord.token": "Discord Bot Token",
|
||||
@@ -131,6 +133,10 @@ const FIELD_HELP: Record<string, string> = {
|
||||
"Ordered fallback image models (provider/model).",
|
||||
"session.agentToAgent.maxPingPongTurns":
|
||||
"Max reply-back turns between requester and target (0–5).",
|
||||
"messages.ackReaction":
|
||||
"Emoji reaction used to acknowledge inbound messages (empty disables).",
|
||||
"messages.ackReactionScope":
|
||||
'When to send ack reactions ("group-mentions", "group-all", "direct", "all").',
|
||||
};
|
||||
|
||||
const FIELD_PLACEHOLDERS: Record<string, string> = {
|
||||
|
||||
@@ -449,6 +449,10 @@ export type RoutingConfig = {
|
||||
export type MessagesConfig = {
|
||||
messagePrefix?: string; // Prefix added to all inbound messages (default: "[clawdbot]" if no allowFrom, else "")
|
||||
responsePrefix?: string; // Prefix auto-added to all outbound replies (e.g., "🦞")
|
||||
/** Emoji reaction used to acknowledge inbound messages (empty disables). */
|
||||
ackReaction?: string;
|
||||
/** When to send ack reactions. Default: "group-mentions". */
|
||||
ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all";
|
||||
};
|
||||
|
||||
export type BridgeBindMode = "auto" | "lan" | "tailnet" | "loopback";
|
||||
|
||||
@@ -150,6 +150,10 @@ const MessagesSchema = z
|
||||
.object({
|
||||
messagePrefix: z.string().optional(),
|
||||
responsePrefix: z.string().optional(),
|
||||
ackReaction: z.string().optional(),
|
||||
ackReactionScope: z
|
||||
.enum(["group-mentions", "group-all", "direct", "all"])
|
||||
.optional(),
|
||||
})
|
||||
.optional();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user