fix(channels): honor reasoning defaults in previews (#71817) (thanks @anagnorisis2peripeteia)

This commit is contained in:
Ayaan Zaidi
2026-05-08 18:09:15 +05:30
parent 5c589673ec
commit 30e079dd89
9 changed files with 153 additions and 10 deletions

View File

@@ -0,0 +1,21 @@
import type { ClawdbotConfig } from "./bot-runtime-api.js";
type ReasoningDefault = "on" | "stream" | "off";
const DEFAULT_AGENT_ID = "main";
function normalizeAgentId(value: string | undefined | null): string {
const normalized = (value ?? "").trim().toLowerCase();
return normalized || DEFAULT_AGENT_ID;
}
export function resolveFeishuConfigReasoningDefault(
cfg: ClawdbotConfig,
agentId: string,
): ReasoningDefault {
const id = normalizeAgentId(agentId);
const agentDefault = cfg.agents?.list?.find(
(entry) => normalizeAgentId(entry?.id) === id,
)?.reasoningDefault;
return agentDefault ?? cfg.agents?.defaults?.reasoningDefault ?? "off";
}

View File

@@ -1357,6 +1357,8 @@ export async function handleFeishuMessage(params: {
},
};
const allowReasoningPreview = resolveFeishuReasoningPreviewEnabled({
cfg,
agentId,
storePath: agentStorePath,
sessionKey: agentSessionKey,
});
@@ -1532,6 +1534,8 @@ export async function handleFeishuMessage(params: {
agentId: route.agentId,
});
const allowReasoningPreview = resolveFeishuReasoningPreviewEnabled({
cfg,
agentId: route.agentId,
storePath,
sessionKey: route.sessionKey,
});

View File

@@ -1,4 +1,5 @@
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { ClawdbotConfig } from "./bot-runtime-api.js";
import { resolveFeishuReasoningPreviewEnabled } from "./reasoning-preview.js";
const { loadSessionStoreMock } = vi.hoisted(() => ({
@@ -20,6 +21,8 @@ afterAll(() => {
});
describe("resolveFeishuReasoningPreviewEnabled", () => {
const emptyCfg: ClawdbotConfig = {};
beforeEach(() => {
vi.clearAllMocks();
});
@@ -32,12 +35,16 @@ describe("resolveFeishuReasoningPreviewEnabled", () => {
expect(
resolveFeishuReasoningPreviewEnabled({
cfg: emptyCfg,
agentId: "main",
storePath: "/tmp/feishu-sessions.json",
sessionKey: "agent:main:feishu:dm:ou_sender_1",
}),
).toBe(true);
expect(
resolveFeishuReasoningPreviewEnabled({
cfg: emptyCfg,
agentId: "main",
storePath: "/tmp/feishu-sessions.json",
sessionKey: "agent:main:feishu:dm:ou_sender_2",
}),
@@ -51,14 +58,56 @@ describe("resolveFeishuReasoningPreviewEnabled", () => {
expect(
resolveFeishuReasoningPreviewEnabled({
cfg: emptyCfg,
agentId: "main",
storePath: "/tmp/feishu-sessions.json",
sessionKey: "agent:main:feishu:dm:ou_sender_1",
}),
).toBe(false);
expect(
resolveFeishuReasoningPreviewEnabled({
cfg: emptyCfg,
agentId: "main",
storePath: "/tmp/feishu-sessions.json",
}),
).toBe(false);
});
it("falls back to configured stream defaults", () => {
loadSessionStoreMock.mockReturnValue({
"agent:main:feishu:dm:ou_sender_1": {},
"agent:main:feishu:dm:ou_sender_2": { reasoningLevel: "off" },
});
const cfg: ClawdbotConfig = {
agents: {
defaults: { reasoningDefault: "stream" },
list: [{ id: "Ops", reasoningDefault: "off" }],
},
};
expect(
resolveFeishuReasoningPreviewEnabled({
cfg,
agentId: "main",
storePath: "/tmp/feishu-sessions.json",
sessionKey: "agent:main:feishu:dm:ou_sender_1",
}),
).toBe(true);
expect(
resolveFeishuReasoningPreviewEnabled({
cfg,
agentId: "ops",
storePath: "/tmp/feishu-sessions.json",
}),
).toBe(false);
expect(
resolveFeishuReasoningPreviewEnabled({
cfg,
agentId: "main",
storePath: "/tmp/feishu-sessions.json",
sessionKey: "agent:main:feishu:dm:ou_sender_2",
}),
).toBe(false);
});
});

View File

@@ -1,20 +1,28 @@
import { resolveFeishuConfigReasoningDefault } from "./agent-config.js";
import { loadSessionStore, resolveSessionStoreEntry } from "./bot-runtime-api.js";
import type { ClawdbotConfig } from "./bot-runtime-api.js";
export function resolveFeishuReasoningPreviewEnabled(params: {
cfg: ClawdbotConfig;
agentId: string;
storePath: string;
sessionKey?: string;
}): boolean {
const configDefault = resolveFeishuConfigReasoningDefault(params.cfg, params.agentId);
if (!params.sessionKey) {
return false;
return configDefault === "stream";
}
try {
const store = loadSessionStore(params.storePath, { skipCache: true });
return (
resolveSessionStoreEntry({ store, sessionKey: params.sessionKey }).existing
?.reasoningLevel === "stream"
);
const level = resolveSessionStoreEntry({ store, sessionKey: params.sessionKey }).existing
?.reasoningLevel;
if (level === "on" || level === "stream" || level === "off") {
return level === "stream";
}
} catch {
return false;
}
return configDefault === "stream";
}