diff --git a/src/auto-reply/reply/directive-handling.levels.test.ts b/src/auto-reply/reply/directive-handling.levels.test.ts index 204d2685005..23c8fc9f745 100644 --- a/src/auto-reply/reply/directive-handling.levels.test.ts +++ b/src/auto-reply/reply/directive-handling.levels.test.ts @@ -33,4 +33,41 @@ describe("resolveCurrentDirectiveLevels", () => { expect(result.currentThinkLevel).toBe("minimal"); expect(resolveDefaultThinkingLevel).not.toHaveBeenCalled(); }); + + // reasoningDefault tests + it("uses agent reasoningDefault when session reasoningLevel is absent", async () => { + const result = await resolveCurrentDirectiveLevels({ + sessionEntry: {}, + agentCfg: { + reasoningDefault: "on", + }, + resolveDefaultThinkingLevel: vi.fn(), + }); + + expect(result.currentReasoningLevel).toBe("on"); + }); + + it("session reasoningLevel overrides agent reasoningDefault", async () => { + const result = await resolveCurrentDirectiveLevels({ + sessionEntry: { + reasoningLevel: "off", + }, + agentCfg: { + reasoningDefault: "on", + }, + resolveDefaultThinkingLevel: vi.fn(), + }); + + expect(result.currentReasoningLevel).toBe("off"); + }); + + it("defaults reasoningLevel to off when neither session nor config is set", async () => { + const result = await resolveCurrentDirectiveLevels({ + sessionEntry: {}, + agentCfg: {}, + resolveDefaultThinkingLevel: vi.fn(), + }); + + expect(result.currentReasoningLevel).toBe("off"); + }); }); diff --git a/src/auto-reply/reply/directive-handling.levels.ts b/src/auto-reply/reply/directive-handling.levels.ts index b62e77c3501..6282c1e1974 100644 --- a/src/auto-reply/reply/directive-handling.levels.ts +++ b/src/auto-reply/reply/directive-handling.levels.ts @@ -10,6 +10,7 @@ export async function resolveCurrentDirectiveLevels(params: { }; agentCfg?: { thinkingDefault?: unknown; + reasoningDefault?: unknown; verboseDefault?: unknown; elevatedDefault?: unknown; }; @@ -32,7 +33,9 @@ export async function resolveCurrentDirectiveLevels(params: { (params.sessionEntry?.verboseLevel as VerboseLevel | undefined) ?? (params.agentCfg?.verboseDefault as VerboseLevel | undefined); const currentReasoningLevel = - (params.sessionEntry?.reasoningLevel as ReasoningLevel | undefined) ?? "off"; + (params.sessionEntry?.reasoningLevel as ReasoningLevel | undefined) ?? + (params.agentCfg?.reasoningDefault as ReasoningLevel | undefined) ?? + "off"; const currentElevatedLevel = (params.sessionEntry?.elevatedLevel as ElevatedLevel | undefined) ?? (params.agentCfg?.elevatedDefault as ElevatedLevel | undefined); diff --git a/src/auto-reply/reply/get-reply-directives.ts b/src/auto-reply/reply/get-reply-directives.ts index 37eef3fb9b8..3f415a40367 100644 --- a/src/auto-reply/reply/get-reply-directives.ts +++ b/src/auto-reply/reply/get-reply-directives.ts @@ -360,6 +360,7 @@ export async function resolveReplyDirectives(params: { let resolvedReasoningLevel: ReasoningLevel = directives.reasoningLevel ?? (sessionEntry?.reasoningLevel as ReasoningLevel | undefined) ?? + (agentCfg?.reasoningDefault as ReasoningLevel | undefined) ?? "off"; const resolvedElevatedLevel = elevatedAllowed ? (directives.elevatedLevel ?? @@ -412,7 +413,8 @@ export async function resolveReplyDirectives(params: { // be emitted as visible "Reasoning:" messages. const reasoningExplicitlySet = directives.reasoningLevel !== undefined || - (sessionEntry?.reasoningLevel !== undefined && sessionEntry?.reasoningLevel !== null); + (sessionEntry?.reasoningLevel !== undefined && sessionEntry?.reasoningLevel !== null) || + agentCfg?.reasoningDefault !== undefined; const thinkingActive = resolvedThinkLevelWithDefault !== "off"; if (!reasoningExplicitlySet && resolvedReasoningLevel === "off" && !thinkingActive) { resolvedReasoningLevel = await modelState.resolveDefaultReasoningLevel(); diff --git a/src/auto-reply/status.ts b/src/auto-reply/status.ts index 1b7aa2a87ec..a0ba5dc4598 100644 --- a/src/auto-reply/status.ts +++ b/src/auto-reply/status.ts @@ -512,7 +512,8 @@ export function buildStatusMessage(args: StatusArgs): string { const verboseLevel = args.resolvedVerbose ?? args.sessionEntry?.verboseLevel ?? args.agent?.verboseDefault ?? "off"; const fastMode = args.resolvedFast ?? args.sessionEntry?.fastMode ?? false; - const reasoningLevel = args.resolvedReasoning ?? args.sessionEntry?.reasoningLevel ?? "off"; + const reasoningLevel = + args.resolvedReasoning ?? args.sessionEntry?.reasoningLevel ?? args.agent?.reasoningDefault ?? "off"; const elevatedLevel = args.resolvedElevated ?? args.sessionEntry?.elevatedLevel ?? diff --git a/src/config/types.agent-defaults.ts b/src/config/types.agent-defaults.ts index ecaaecb69b9..165a3a62258 100644 --- a/src/config/types.agent-defaults.ts +++ b/src/config/types.agent-defaults.ts @@ -187,6 +187,8 @@ export type AgentDefaultsConfig = { memorySearch?: MemorySearchConfig; /** Default thinking level when no /think directive is present. */ thinkingDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive"; + /** Default reasoning display level when no /reasoning directive is present. */ + reasoningDefault?: "off" | "on" | "stream"; /** Default verbose level when no /verbose directive is present. */ verboseDefault?: "off" | "on" | "full"; /** Default elevated level when no /elevated directive is present. */ diff --git a/src/config/zod-schema.agent-defaults.ts b/src/config/zod-schema.agent-defaults.ts index 836a1fdae91..8f82d636629 100644 --- a/src/config/zod-schema.agent-defaults.ts +++ b/src/config/zod-schema.agent-defaults.ts @@ -148,6 +148,9 @@ export const AgentDefaultsSchema = z z.literal("adaptive"), ]) .optional(), + reasoningDefault: z + .union([z.literal("off"), z.literal("on"), z.literal("stream")]) + .optional(), verboseDefault: z.union([z.literal("off"), z.literal("on"), z.literal("full")]).optional(), elevatedDefault: z .union([z.literal("off"), z.literal("on"), z.literal("ask"), z.literal("full")])